console.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package muesli
  2. import "io"
  3. import "fmt"
  4. import "os"
  5. // Consoler is an interface to a virtual console that the VM 's frames use for
  6. // stdin, stdout, stderr, and logging output.
  7. // This allows you to redirect the output of the VM and any built-in functions
  8. // to whatever you like.
  9. type Consoler interface {
  10. LogTo() io.Writer // logs should be written to this writer of not nil
  11. Out() io.Writer // standard output goes to this writer of not nil.
  12. Err() io.Writer // standard error go to this writer if not nil
  13. In() io.Reader // can read standard input from this reader if not nil
  14. }
  15. // BasicConsole is a reusable virtual console struct.
  16. // It implements the BasicConsoler interface
  17. type BasicConsole struct {
  18. log io.Writer
  19. out io.Writer
  20. err io.Writer
  21. in io.Reader
  22. }
  23. func (c BasicConsole) LogTo() io.Writer {
  24. return c.log
  25. }
  26. func (c BasicConsole) Out() io.Writer {
  27. return c.out
  28. }
  29. func (c BasicConsole) Err() io.Writer {
  30. return c.err
  31. }
  32. func (c BasicConsole) In() io.Reader {
  33. return c.in
  34. }
  35. func NewBasicConsole(log, out, err io.Writer, in io.Reader) BasicConsole {
  36. return BasicConsole { log, out, err, in }
  37. }
  38. var _ Consoler = BasicConsole{}
  39. // Console is a fully features wrapper BasicConsole, easier to use with Printf
  40. // and Log, etc, and implements the Logger and Consoler interface.
  41. type Console struct {
  42. LoggerWrapper
  43. Consoler
  44. }
  45. func (c *Console) Fprintf(out io.Writer, format string, args ... interface{}) (int, error) {
  46. if out != nil {
  47. return fmt.Fprintf(out, format, args...)
  48. }
  49. return 0, nil
  50. }
  51. func (c *Console) Fprintln(out io.Writer, args ... interface{}) (int, error) {
  52. if out != nil {
  53. return fmt.Fprintln(out, args...)
  54. }
  55. return 0, nil
  56. }
  57. func (c *Console) Log(level string, file string, line int, format string, args ...interface{}) {
  58. log := c.Consoler.LogTo()
  59. c.Fprintf(log, "%s:%s:%d: ", level, file, line)
  60. c.Fprintf(log, format, args...)
  61. }
  62. func (c *Console) Printf(format string, args ...interface{}) {
  63. out := c.Out()
  64. c.Fprintf(out, format, args...)
  65. }
  66. func (c *Console) Println(args ...interface{}) {
  67. out := c.Out()
  68. c.Fprintln(out, args...)
  69. }
  70. func (c *Console) Errf(format string, args ...interface{}) {
  71. err := c.Err()
  72. c.Fprintf(err, format, args...)
  73. }
  74. func NewConsole(log, out, err io.Writer, in io.Reader) *Console {
  75. console := &Console{}
  76. console.Consoler = NewBasicConsole(log, out, err, in)
  77. return console
  78. }
  79. // also implement the tracer interface
  80. func (c *Console) Trace(vm VM, format string, args ... interface{}) bool {
  81. args = append([]interface{}{vm.BackTrace()}, args...)
  82. c.LogTrace("%s: " + format, args...)
  83. return false
  84. }
  85. func NewStdConsole() *Console {
  86. return NewConsole(os.Stdout, os.Stdout, os.Stderr, os.Stdin)
  87. }