mirror of
				https://github.com/robertkrimen/otto
				synced 2025-10-26 20:28:49 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			388 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) from github.com/robertkrimen/dbg
 | |
| 
 | |
| /*
 | |
| Package dbg is a println/printf/log-debugging utility library.
 | |
| 
 | |
|     import (
 | |
|         Dbg "github.com/robertkrimen/dbg"
 | |
|     )
 | |
| 
 | |
|     dbg, dbgf := Dbg.New()
 | |
| 
 | |
|     dbg("Emit some debug stuff", []byte{120, 121, 122, 122, 121}, math.Pi)
 | |
|     # "2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793"
 | |
| 
 | |
|     dbgf("With a %s formatting %.2f", "little", math.Pi)
 | |
|     # "2013/01/28 16:51:55 With a little formatting (3.14)"
 | |
| 
 | |
|     dbgf("%/fatal//A fatal debug statement: should not be here")
 | |
|     # "A fatal debug statement: should not be here"
 | |
|     # ...and then, os.Exit(1)
 | |
| 
 | |
|     dbgf("%/panic//Can also panic %s", "this")
 | |
|     # "Can also panic this"
 | |
|     # ...as a panic, equivalent to: panic("Can also panic this")
 | |
| 
 | |
|     dbgf("Any %s arguments without a corresponding %%", "extra", "are treated like arguments to dbg()")
 | |
|     # "2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()"
 | |
| 
 | |
|     dbgf("%d %d", 1, 2, 3, 4, 5)
 | |
|     # "2013/01/28 17:16:32 Another example: 1 2 3 4 5"
 | |
| 
 | |
|     dbgf("%@: Include the function name for a little context (via %s)", "%@")
 | |
|     # "2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)"
 | |
| 
 | |
| By default, dbg uses log (log.Println, log.Printf, log.Panic, etc.) for output.
 | |
| However, you can also provide your own output destination by invoking dbg.New with
 | |
| a customization function:
 | |
| 
 | |
|     import (
 | |
|         "bytes"
 | |
|         Dbg "github.com/robertkrimen/dbg"
 | |
|         "os"
 | |
|     )
 | |
| 
 | |
|     # dbg to os.Stderr
 | |
|     dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
 | |
|         dbgr.SetOutput(os.Stderr)
 | |
|     })
 | |
| 
 | |
|     # A slightly contrived example:
 | |
|     var buffer bytes.Buffer
 | |
|     dbg, dbgf := New(func(dbgr *Dbgr) {
 | |
|         dbgr.SetOutput(&buffer)
 | |
|     })
 | |
| 
 | |
| */
 | |
| package dbg
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"log"
 | |
| 	"os"
 | |
| 	"regexp"
 | |
| 	"runtime"
 | |
| 	"strings"
 | |
| 	"unicode"
 | |
| )
 | |
| 
 | |
| type _frmt struct {
 | |
| 	ctl          string
 | |
| 	format       string
 | |
| 	operandCount int
 | |
| 	panic        bool
 | |
| 	fatal        bool
 | |
| 	check        bool
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	ctlTest = regexp.MustCompile(`^\s*%/`)
 | |
| 	ctlScan = regexp.MustCompile(`%?/(panic|fatal|check)(?:\s|$)`)
 | |
| )
 | |
| 
 | |
| func operandCount(format string) int {
 | |
| 	count := 0
 | |
| 	end := len(format)
 | |
| 	for at := 0; at < end; {
 | |
| 		for at < end && format[at] != '%' {
 | |
| 			at++
 | |
| 		}
 | |
| 		at++
 | |
| 		if at < end {
 | |
| 			if format[at] != '%' && format[at] != '@' {
 | |
| 				count++
 | |
| 			}
 | |
| 			at++
 | |
| 		}
 | |
| 	}
 | |
| 	return count
 | |
| }
 | |
| 
 | |
| func parseFormat(format string) (frmt _frmt) {
 | |
| 	if ctlTest.MatchString(format) {
 | |
| 		format = strings.TrimLeftFunc(format, unicode.IsSpace)
 | |
| 		index := strings.Index(format, "//")
 | |
| 		if index != -1 {
 | |
| 			frmt.ctl = format[0:index]
 | |
| 			format = format[index+2:] // Skip the second slash via +2 (instead of +1)
 | |
| 		} else {
 | |
| 			frmt.ctl = format
 | |
| 			format = ""
 | |
| 		}
 | |
| 		for _, tmp := range ctlScan.FindAllStringSubmatch(frmt.ctl, -1) {
 | |
| 			for _, value := range tmp[1:] {
 | |
| 				switch value {
 | |
| 				case "panic":
 | |
| 					frmt.panic = true
 | |
| 				case "fatal":
 | |
| 					frmt.fatal = true
 | |
| 				case "check":
 | |
| 					frmt.check = true
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	frmt.format = format
 | |
| 	frmt.operandCount = operandCount(format)
 | |
| 	return
 | |
| }
 | |
| 
 | |
| type Dbgr struct {
 | |
| 	emit _emit
 | |
| }
 | |
| 
 | |
| type DbgFunction func(values ...interface{})
 | |
| 
 | |
| func NewDbgr() *Dbgr {
 | |
| 	self := &Dbgr{}
 | |
| 	return self
 | |
| }
 | |
| 
 | |
| /*
 | |
| New will create and return a pair of debugging functions. You can customize where
 | |
| they output to by passing in an (optional) customization function:
 | |
| 
 | |
|     import (
 | |
|         Dbg "github.com/robertkrimen/dbg"
 | |
|         "os"
 | |
|     )
 | |
| 
 | |
|     # dbg to os.Stderr
 | |
|     dbg, dbgf := Dbg.New(func(dbgr *Dbgr) {
 | |
|         dbgr.SetOutput(os.Stderr)
 | |
|     })
 | |
| 
 | |
| */
 | |
| func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {
 | |
| 	dbgr := NewDbgr()
 | |
| 	if len(options) > 0 {
 | |
| 		if fn, ok := options[0].(func(*Dbgr)); ok {
 | |
| 			fn(dbgr)
 | |
| 		}
 | |
| 	}
 | |
| 	return dbgr.DbgDbgf()
 | |
| }
 | |
| 
 | |
| func (self Dbgr) Dbg(values ...interface{}) {
 | |
| 	self.getEmit().emit(_frmt{}, "", values...)
 | |
| }
 | |
| 
 | |
| func (self Dbgr) Dbgf(values ...interface{}) {
 | |
| 	self.dbgf(values...)
 | |
| }
 | |
| 
 | |
| func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {
 | |
| 	dbg = func(vl ...interface{}) {
 | |
| 		self.Dbg(vl...)
 | |
| 	}
 | |
| 	dbgf = func(vl ...interface{}) {
 | |
| 		self.dbgf(vl...)
 | |
| 	}
 | |
| 	return dbg, dbgf // Redundant, but...
 | |
| }
 | |
| 
 | |
| func (self Dbgr) dbgf(values ...interface{}) {
 | |
| 
 | |
| 	var frmt _frmt
 | |
| 	if len(values) > 0 {
 | |
| 		tmp := fmt.Sprint(values[0])
 | |
| 		frmt = parseFormat(tmp)
 | |
| 		values = values[1:]
 | |
| 	}
 | |
| 
 | |
| 	buffer_f := bytes.Buffer{}
 | |
| 	format := frmt.format
 | |
| 	end := len(format)
 | |
| 	for at := 0; at < end; {
 | |
| 		last := at
 | |
| 		for at < end && format[at] != '%' {
 | |
| 			at++
 | |
| 		}
 | |
| 		if at > last {
 | |
| 			buffer_f.WriteString(format[last:at])
 | |
| 		}
 | |
| 		if at >= end {
 | |
| 			break
 | |
| 		}
 | |
| 		// format[at] == '%'
 | |
| 		at++
 | |
| 		// format[at] == ?
 | |
| 		if format[at] == '@' {
 | |
| 			depth := 2
 | |
| 			pc, _, _, _ := runtime.Caller(depth)
 | |
| 			name := runtime.FuncForPC(pc).Name()
 | |
| 			buffer_f.WriteString(name)
 | |
| 		} else {
 | |
| 			buffer_f.WriteString(format[at-1 : at+1])
 | |
| 		}
 | |
| 		at++
 | |
| 	}
 | |
| 
 | |
| 	//values_f := append([]interface{}{}, values[0:frmt.operandCount]...)
 | |
| 	values_f := values[0:frmt.operandCount]
 | |
| 	values_dbg := values[frmt.operandCount:]
 | |
| 	if len(values_dbg) > 0 {
 | |
| 		// Adjust frmt.format:
 | |
| 		// (%v instead of %s because: frmt.check)
 | |
| 		{
 | |
| 			tmp := format
 | |
| 			if len(tmp) > 0 {
 | |
| 				if unicode.IsSpace(rune(tmp[len(tmp)-1])) {
 | |
| 					buffer_f.WriteString("%v")
 | |
| 				} else {
 | |
| 					buffer_f.WriteString(" %v")
 | |
| 				}
 | |
| 			} else if frmt.check {
 | |
| 				// Performing a check, so no output
 | |
| 			} else {
 | |
| 				buffer_f.WriteString("%v")
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Adjust values_f:
 | |
| 		if !frmt.check {
 | |
| 			tmp := []string{}
 | |
| 			for _, value := range values_dbg {
 | |
| 				tmp = append(tmp, fmt.Sprintf("%v", value))
 | |
| 			}
 | |
| 			// First, make a copy of values_f, so we avoid overwriting values_dbg when appending
 | |
| 			values_f = append([]interface{}{}, values_f...)
 | |
| 			values_f = append(values_f, strings.Join(tmp, " "))
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	format = buffer_f.String()
 | |
| 	if frmt.check {
 | |
| 		// We do not actually emit to the log, but panic if
 | |
| 		// a non-nil value is detected (e.g. a non-nil error)
 | |
| 		for _, value := range values_dbg {
 | |
| 			if value != nil {
 | |
| 				if format == "" {
 | |
| 					panic(value)
 | |
| 				} else {
 | |
| 					panic(fmt.Sprintf(format, append(values_f, value)...))
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	} else {
 | |
| 		self.getEmit().emit(frmt, format, values_f...)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Idiot-proof &Dbgr{}, etc.
 | |
| func (self *Dbgr) getEmit() _emit {
 | |
| 	if self.emit == nil {
 | |
| 		self.emit = standardEmit()
 | |
| 	}
 | |
| 	return self.emit
 | |
| }
 | |
| 
 | |
| // SetOutput will accept the following as a destination for output:
 | |
| //
 | |
| //      *log.Logger         Print*/Panic*/Fatal* of the logger
 | |
| //      io.Writer           -
 | |
| //      nil                 Reset to the default output (os.Stderr)
 | |
| //      "log"               Print*/Panic*/Fatal* via the "log" package
 | |
| //
 | |
| func (self *Dbgr) SetOutput(output interface{}) {
 | |
| 	if output == nil {
 | |
| 		self.emit = standardEmit()
 | |
| 		return
 | |
| 	}
 | |
| 	switch output := output.(type) {
 | |
| 	case *log.Logger:
 | |
| 		self.emit = _emitLogger{
 | |
| 			logger: output,
 | |
| 		}
 | |
| 		return
 | |
| 	case io.Writer:
 | |
| 		self.emit = _emitWriter{
 | |
| 			writer: output,
 | |
| 		}
 | |
| 		return
 | |
| 	case string:
 | |
| 		if output == "log" {
 | |
| 			self.emit = _emitLog{}
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	panic(output)
 | |
| }
 | |
| 
 | |
| // ======== //
 | |
| // = emit = //
 | |
| // ======== //
 | |
| 
 | |
| func standardEmit() _emit {
 | |
| 	return _emitWriter{
 | |
| 		writer: os.Stderr,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func ln(tmp string) string {
 | |
| 	length := len(tmp)
 | |
| 	if length > 0 && tmp[length-1] != '\n' {
 | |
| 		return tmp + "\n"
 | |
| 	}
 | |
| 	return tmp
 | |
| }
 | |
| 
 | |
| type _emit interface {
 | |
| 	emit(_frmt, string, ...interface{})
 | |
| }
 | |
| 
 | |
| type _emitWriter struct {
 | |
| 	writer io.Writer
 | |
| }
 | |
| 
 | |
| func (self _emitWriter) emit(frmt _frmt, format string, values ...interface{}) {
 | |
| 	if format == "" {
 | |
| 		fmt.Fprintln(self.writer, values...)
 | |
| 	} else {
 | |
| 		if frmt.panic {
 | |
| 			panic(fmt.Sprintf(format, values...))
 | |
| 		}
 | |
| 		fmt.Fprintf(self.writer, ln(format), values...)
 | |
| 		if frmt.fatal {
 | |
| 			os.Exit(1)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type _emitLogger struct {
 | |
| 	logger *log.Logger
 | |
| }
 | |
| 
 | |
| func (self _emitLogger) emit(frmt _frmt, format string, values ...interface{}) {
 | |
| 	if format == "" {
 | |
| 		self.logger.Println(values...)
 | |
| 	} else {
 | |
| 		if frmt.panic {
 | |
| 			self.logger.Panicf(format, values...)
 | |
| 		} else if frmt.fatal {
 | |
| 			self.logger.Fatalf(format, values...)
 | |
| 		} else {
 | |
| 			self.logger.Printf(format, values...)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type _emitLog struct {
 | |
| }
 | |
| 
 | |
| func (self _emitLog) emit(frmt _frmt, format string, values ...interface{}) {
 | |
| 	if format == "" {
 | |
| 		log.Println(values...)
 | |
| 	} else {
 | |
| 		if frmt.panic {
 | |
| 			log.Panicf(format, values...)
 | |
| 		} else if frmt.fatal {
 | |
| 			log.Fatalf(format, values...)
 | |
| 		} else {
 | |
| 			log.Printf(format, values...)
 | |
| 		}
 | |
| 	}
 | |
| }
 | 
