diff --git a/Gopkg.lock b/Gopkg.lock
index 0295e8c29ec5131bd69db7846318494bd98eccdf..d4323f62ad5209a52ad7924f0b9f092993a80417 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -18,14 +18,15 @@
   version = "v0.25.0"
 
 [[projects]]
-  digest = "1:03a488e7484b135ddd9c05360fce30ad74ff7513823fc7dcbda1801d66d553d0"
+  branch = "master"
+  digest = "1:c7fe86f3f0c5dec0516cf2f139e91c61fa96742a3f3c983f325f4e6d630e748f"
   name = "github.com/Azure/go-ansiterm"
   packages = [
     ".",
     "winterm",
   ]
   pruneopts = "N"
-  revision = "19f72df4d05d31cbe1c56bfc8045c96babff6c7e"
+  revision = "d6e3b3328b783f23731bc4d058875b0371ff8109"
 
 [[projects]]
   digest = "1:c522948b37859d83d8cc338d81cd2f4e838ee351ab8c23b41c1afa9bf7f80351"
diff --git a/Gopkg.toml b/Gopkg.toml
index ddd51c75b3396e8e9490643a2f1359d6d24b62fc..b6566416d8550c375a7ef1ac08c6930668e9e537 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -158,10 +158,6 @@ ignored = ["test", "appengine"]
   name = "github.com/Azure/go-autorest"
   revision = "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab"
 
-[[override]]
-  name = "github.com/Azure/go-ansiterm"
-  revision = "19f72df4d05d31cbe1c56bfc8045c96babff6c7e"
-
 [[override]]
   name = "github.com/Microsoft/go-winio"
   revision = "ce2922f643c8fd76b46cadc7f404a06282678b34"
diff --git a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go
index 1bd6057da8a8e0d1006cafad968e099af8be9263..bcbe00d0c5ec273971688cd161047b667d39865b 100644
--- a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go
+++ b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go
@@ -5,7 +5,7 @@ type csiEntryState struct {
 }
 
 func (csiState csiEntryState) Handle(b byte) (s state, e error) {
-	logger.Infof("CsiEntry::Handle %#x", b)
+	csiState.parser.logf("CsiEntry::Handle %#x", b)
 
 	nextState, err := csiState.baseState.Handle(b)
 	if nextState != nil || err != nil {
@@ -25,7 +25,7 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) {
 }
 
 func (csiState csiEntryState) Transition(s state) error {
-	logger.Infof("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name())
+	csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name())
 	csiState.baseState.Transition(s)
 
 	switch s {
diff --git a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go
index 4be35c5fd2af7a0722a157d9540f56e511981b15..7ed5e01c34281986f3f6b5e106108816217ee3ca 100644
--- a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go
+++ b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go
@@ -5,7 +5,7 @@ type csiParamState struct {
 }
 
 func (csiState csiParamState) Handle(b byte) (s state, e error) {
-	logger.Infof("CsiParam::Handle %#x", b)
+	csiState.parser.logf("CsiParam::Handle %#x", b)
 
 	nextState, err := csiState.baseState.Handle(b)
 	if nextState != nil || err != nil {
@@ -26,7 +26,7 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) {
 }
 
 func (csiState csiParamState) Transition(s state) error {
-	logger.Infof("CsiParam::Transition %s --> %s", csiState.Name(), s.Name())
+	csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name())
 	csiState.baseState.Transition(s)
 
 	switch s {
diff --git a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go
index 2189eb6b6b06575a66de51557f25756ef0669e77..1c719db9e48cdd8462d2c26b45b11d0460d0b5b4 100644
--- a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go
+++ b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go
@@ -5,7 +5,7 @@ type escapeIntermediateState struct {
 }
 
 func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
-	logger.Infof("escapeIntermediateState::Handle %#x", b)
+	escState.parser.logf("escapeIntermediateState::Handle %#x", b)
 	nextState, err := escState.baseState.Handle(b)
 	if nextState != nil || err != nil {
 		return nextState, err
@@ -24,7 +24,7 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
 }
 
 func (escState escapeIntermediateState) Transition(s state) error {
-	logger.Infof("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name())
+	escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name())
 	escState.baseState.Transition(s)
 
 	switch s {
diff --git a/vendor/github.com/Azure/go-ansiterm/escape_state.go b/vendor/github.com/Azure/go-ansiterm/escape_state.go
index 7b1b9ad3f12e732c8641583ac1b577dc5a980692..6390abd231bac485a500b7ac96b8672b70cebe97 100644
--- a/vendor/github.com/Azure/go-ansiterm/escape_state.go
+++ b/vendor/github.com/Azure/go-ansiterm/escape_state.go
@@ -5,7 +5,7 @@ type escapeState struct {
 }
 
 func (escState escapeState) Handle(b byte) (s state, e error) {
-	logger.Infof("escapeState::Handle %#x", b)
+	escState.parser.logf("escapeState::Handle %#x", b)
 	nextState, err := escState.baseState.Handle(b)
 	if nextState != nil || err != nil {
 		return nextState, err
@@ -28,7 +28,7 @@ func (escState escapeState) Handle(b byte) (s state, e error) {
 }
 
 func (escState escapeState) Transition(s state) error {
-	logger.Infof("Escape::Transition %s --> %s", escState.Name(), s.Name())
+	escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name())
 	escState.baseState.Transition(s)
 
 	switch s {
diff --git a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
index 24062d420ebea5e02cb813535820ee183ff77b54..593b10ab69633012400447dd95191bba2dd53a50 100644
--- a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
+++ b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go
@@ -5,7 +5,7 @@ type oscStringState struct {
 }
 
 func (oscState oscStringState) Handle(b byte) (s state, e error) {
-	logger.Infof("OscString::Handle %#x", b)
+	oscState.parser.logf("OscString::Handle %#x", b)
 	nextState, err := oscState.baseState.Handle(b)
 	if nextState != nil || err != nil {
 		return nextState, err
diff --git a/vendor/github.com/Azure/go-ansiterm/parser.go b/vendor/github.com/Azure/go-ansiterm/parser.go
index 3286a9cb5e362fc38e31334609e7127f19c14a6f..03cec7ada62a548179a547f5c1d66eb9f0593a8f 100644
--- a/vendor/github.com/Azure/go-ansiterm/parser.go
+++ b/vendor/github.com/Azure/go-ansiterm/parser.go
@@ -2,14 +2,10 @@ package ansiterm
 
 import (
 	"errors"
-	"io/ioutil"
+	"log"
 	"os"
-
-	"github.com/sirupsen/logrus"
 )
 
-var logger *logrus.Logger
-
 type AnsiParser struct {
 	currState          state
 	eventHandler       AnsiEventHandler
@@ -23,50 +19,69 @@ type AnsiParser struct {
 	ground             state
 	oscString          state
 	stateMap           []state
+
+	logf func(string, ...interface{})
 }
 
-func CreateParser(initialState string, evtHandler AnsiEventHandler) *AnsiParser {
-	logFile := ioutil.Discard
+type Option func(*AnsiParser)
 
-	if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" {
-		logFile, _ = os.Create("ansiParser.log")
-	}
-
-	logger = &logrus.Logger{
-		Out:       logFile,
-		Formatter: new(logrus.TextFormatter),
-		Level:     logrus.InfoLevel,
+func WithLogf(f func(string, ...interface{})) Option {
+	return func(ap *AnsiParser) {
+		ap.logf = f
 	}
+}
 
-	parser := &AnsiParser{
+func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser {
+	ap := &AnsiParser{
 		eventHandler: evtHandler,
 		context:      &ansiContext{},
 	}
+	for _, o := range opts {
+		o(ap)
+	}
+
+	if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" {
+		logFile, _ := os.Create("ansiParser.log")
+		logger := log.New(logFile, "", log.LstdFlags)
+		if ap.logf != nil {
+			l := ap.logf
+			ap.logf = func(s string, v ...interface{}) {
+				l(s, v...)
+				logger.Printf(s, v...)
+			}
+		} else {
+			ap.logf = logger.Printf
+		}
+	}
+
+	if ap.logf == nil {
+		ap.logf = func(string, ...interface{}) {}
+	}
 
-	parser.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: parser}}
-	parser.csiParam = csiParamState{baseState{name: "CsiParam", parser: parser}}
-	parser.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: parser}}
-	parser.escape = escapeState{baseState{name: "Escape", parser: parser}}
-	parser.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: parser}}
-	parser.error = errorState{baseState{name: "Error", parser: parser}}
-	parser.ground = groundState{baseState{name: "Ground", parser: parser}}
-	parser.oscString = oscStringState{baseState{name: "OscString", parser: parser}}
-
-	parser.stateMap = []state{
-		parser.csiEntry,
-		parser.csiParam,
-		parser.dcsEntry,
-		parser.escape,
-		parser.escapeIntermediate,
-		parser.error,
-		parser.ground,
-		parser.oscString,
+	ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}}
+	ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}}
+	ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}}
+	ap.escape = escapeState{baseState{name: "Escape", parser: ap}}
+	ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}}
+	ap.error = errorState{baseState{name: "Error", parser: ap}}
+	ap.ground = groundState{baseState{name: "Ground", parser: ap}}
+	ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}}
+
+	ap.stateMap = []state{
+		ap.csiEntry,
+		ap.csiParam,
+		ap.dcsEntry,
+		ap.escape,
+		ap.escapeIntermediate,
+		ap.error,
+		ap.ground,
+		ap.oscString,
 	}
 
-	parser.currState = getState(initialState, parser.stateMap)
+	ap.currState = getState(initialState, ap.stateMap)
 
-	logger.Infof("CreateParser: parser %p", parser)
-	return parser
+	ap.logf("CreateParser: parser %p", ap)
+	return ap
 }
 
 func getState(name string, states []state) state {
@@ -97,7 +112,7 @@ func (ap *AnsiParser) handle(b byte) error {
 	}
 
 	if newState == nil {
-		logger.Warning("newState is nil")
+		ap.logf("WARNING: newState is nil")
 		return errors.New("New state of 'nil' is invalid.")
 	}
 
@@ -111,23 +126,23 @@ func (ap *AnsiParser) handle(b byte) error {
 }
 
 func (ap *AnsiParser) changeState(newState state) error {
-	logger.Infof("ChangeState %s --> %s", ap.currState.Name(), newState.Name())
+	ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name())
 
 	// Exit old state
 	if err := ap.currState.Exit(); err != nil {
-		logger.Infof("Exit state '%s' failed with : '%v'", ap.currState.Name(), err)
+		ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err)
 		return err
 	}
 
 	// Perform transition action
 	if err := ap.currState.Transition(newState); err != nil {
-		logger.Infof("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err)
+		ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err)
 		return err
 	}
 
 	// Enter new state
 	if err := newState.Enter(); err != nil {
-		logger.Infof("Enter state '%s' failed with: '%v'", newState.Name(), err)
+		ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err)
 		return err
 	}
 
diff --git a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go
index 8b69a67a5aa18b4ccebe60ee0e394d6eeec1d1fd..de0a1f9cde3bd8230f535407612570394a4282c5 100644
--- a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go
+++ b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go
@@ -27,7 +27,6 @@ func parseParams(bytes []byte) ([]string, error) {
 		params = append(params, s)
 	}
 
-	logger.Infof("Parsed params: %v with length: %d", params, len(params))
 	return params, nil
 }
 
@@ -37,7 +36,6 @@ func parseCmd(context ansiContext) (string, error) {
 
 func getInt(params []string, dflt int) int {
 	i := getInts(params, 1, dflt)[0]
-	logger.Infof("getInt: %v", i)
 	return i
 }
 
@@ -60,8 +58,6 @@ func getInts(params []string, minCount int, dflt int) []int {
 		}
 	}
 
-	logger.Infof("getInts: %v", ints)
-
 	return ints
 }
 
diff --git a/vendor/github.com/Azure/go-ansiterm/parser_actions.go b/vendor/github.com/Azure/go-ansiterm/parser_actions.go
index 58750a2d2b1b4a47a65c0143241d842e5f0efc09..0bb5e51e9aa60e9df5039df5674f251290c76899 100644
--- a/vendor/github.com/Azure/go-ansiterm/parser_actions.go
+++ b/vendor/github.com/Azure/go-ansiterm/parser_actions.go
@@ -1,19 +1,15 @@
 package ansiterm
 
-import (
-	"fmt"
-)
-
 func (ap *AnsiParser) collectParam() error {
 	currChar := ap.context.currentChar
-	logger.Infof("collectParam %#x", currChar)
+	ap.logf("collectParam %#x", currChar)
 	ap.context.paramBuffer = append(ap.context.paramBuffer, currChar)
 	return nil
 }
 
 func (ap *AnsiParser) collectInter() error {
 	currChar := ap.context.currentChar
-	logger.Infof("collectInter %#x", currChar)
+	ap.logf("collectInter %#x", currChar)
 	ap.context.paramBuffer = append(ap.context.interBuffer, currChar)
 	return nil
 }
@@ -21,8 +17,8 @@ func (ap *AnsiParser) collectInter() error {
 func (ap *AnsiParser) escDispatch() error {
 	cmd, _ := parseCmd(*ap.context)
 	intermeds := ap.context.interBuffer
-	logger.Infof("escDispatch currentChar: %#x", ap.context.currentChar)
-	logger.Infof("escDispatch: %v(%v)", cmd, intermeds)
+	ap.logf("escDispatch currentChar: %#x", ap.context.currentChar)
+	ap.logf("escDispatch: %v(%v)", cmd, intermeds)
 
 	switch cmd {
 	case "D": // IND
@@ -43,8 +39,9 @@ func (ap *AnsiParser) escDispatch() error {
 func (ap *AnsiParser) csiDispatch() error {
 	cmd, _ := parseCmd(*ap.context)
 	params, _ := parseParams(ap.context.paramBuffer)
+	ap.logf("Parsed params: %v with length: %d", params, len(params))
 
-	logger.Infof("csiDispatch: %v(%v)", cmd, params)
+	ap.logf("csiDispatch: %v(%v)", cmd, params)
 
 	switch cmd {
 	case "@":
@@ -102,7 +99,7 @@ func (ap *AnsiParser) csiDispatch() error {
 		top, bottom := ints[0], ints[1]
 		return ap.eventHandler.DECSTBM(top, bottom)
 	default:
-		logger.Errorf(fmt.Sprintf("Unsupported CSI command: '%s', with full context:  %v", cmd, ap.context))
+		ap.logf("ERROR: Unsupported CSI command: '%s', with full context:  %v", cmd, ap.context)
 		return nil
 	}
 
diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go
index daf2f06961588722360fd282e4c68438f79b19e6..a6732797263ffcfb52c6f8436a6a3497195a6e1a 100644
--- a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go
+++ b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go
@@ -175,7 +175,7 @@ func GetStdFile(nFile int) (*os.File, uintptr) {
 
 	fd, err := syscall.GetStdHandle(nFile)
 	if err != nil {
-		panic(fmt.Errorf("Invalid standard handle indentifier: %v -- %v", nFile, err))
+		panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err))
 	}
 
 	return file, uintptr(fd)
diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/api.go b/vendor/github.com/Azure/go-ansiterm/winterm/api.go
index 462d92f8ef9f8daedf7b0f66de36f9fe653af41c..6055e33b912b2be3eafb60c77684f1843e174f1b 100644
--- a/vendor/github.com/Azure/go-ansiterm/winterm/api.go
+++ b/vendor/github.com/Azure/go-ansiterm/winterm/api.go
@@ -49,17 +49,22 @@ var (
 const (
 	// Console modes
 	// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
-	ENABLE_PROCESSED_INPUT = 0x0001
-	ENABLE_LINE_INPUT      = 0x0002
-	ENABLE_ECHO_INPUT      = 0x0004
-	ENABLE_WINDOW_INPUT    = 0x0008
-	ENABLE_MOUSE_INPUT     = 0x0010
-	ENABLE_INSERT_MODE     = 0x0020
-	ENABLE_QUICK_EDIT_MODE = 0x0040
-	ENABLE_EXTENDED_FLAGS  = 0x0080
-
-	ENABLE_PROCESSED_OUTPUT   = 0x0001
-	ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
+	ENABLE_PROCESSED_INPUT        = 0x0001
+	ENABLE_LINE_INPUT             = 0x0002
+	ENABLE_ECHO_INPUT             = 0x0004
+	ENABLE_WINDOW_INPUT           = 0x0008
+	ENABLE_MOUSE_INPUT            = 0x0010
+	ENABLE_INSERT_MODE            = 0x0020
+	ENABLE_QUICK_EDIT_MODE        = 0x0040
+	ENABLE_EXTENDED_FLAGS         = 0x0080
+	ENABLE_AUTO_POSITION          = 0x0100
+	ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
+
+	ENABLE_PROCESSED_OUTPUT            = 0x0001
+	ENABLE_WRAP_AT_EOL_OUTPUT          = 0x0002
+	ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
+	DISABLE_NEWLINE_AUTO_RETURN        = 0x0008
+	ENABLE_LVB_GRID_WORLDWIDE          = 0x0010
 
 	// Character attributes
 	// Note:
diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go
index f015723ade79efdc3702fd291571000337e0207d..3ee06ea728249a7463c44ccdb4ba3673577147f7 100644
--- a/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go
+++ b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go
@@ -34,7 +34,7 @@ func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL
 	if err != nil {
 		return err
 	}
-	logger.Infof("Cursor position set: (%d, %d)", position.X, position.Y)
+	h.logf("Cursor position set: (%d, %d)", position.X, position.Y)
 	return err
 }
 
diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go
index 706d270577e3d72f81843189badd55db04b0d11d..2d27fa1d028866c21c180baa2b538ef2f1e02747 100644
--- a/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go
+++ b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go
@@ -50,8 +50,8 @@ func (h *windowsAnsiEventHandler) insertLines(param int) error {
 
 // scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates.
 func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error {
-	logger.Infof("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom)
-	logger.Infof("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom)
+	h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom)
+	h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom)
 
 	// Copy from and clip to the scroll region (full buffer width)
 	scrollRect := SMALL_RECT{
diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go
index 48998bb051e7cd83a2b5315456ba1fe0c29893cd..2d40fb75ad0bb384221f15a575eb1eb288e76eb1 100644
--- a/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go
+++ b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go
@@ -4,16 +4,13 @@ package winterm
 
 import (
 	"bytes"
-	"io/ioutil"
+	"log"
 	"os"
 	"strconv"
 
 	"github.com/Azure/go-ansiterm"
-	"github.com/sirupsen/logrus"
 )
 
-var logger *logrus.Logger
-
 type windowsAnsiEventHandler struct {
 	fd             uintptr
 	file           *os.File
@@ -28,32 +25,52 @@ type windowsAnsiEventHandler struct {
 	marginByte     byte
 	curInfo        *CONSOLE_SCREEN_BUFFER_INFO
 	curPos         COORD
+	logf           func(string, ...interface{})
 }
 
-func CreateWinEventHandler(fd uintptr, file *os.File) ansiterm.AnsiEventHandler {
-	logFile := ioutil.Discard
-
-	if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
-		logFile, _ = os.Create("winEventHandler.log")
-	}
+type Option func(*windowsAnsiEventHandler)
 
-	logger = &logrus.Logger{
-		Out:       logFile,
-		Formatter: new(logrus.TextFormatter),
-		Level:     logrus.DebugLevel,
+func WithLogf(f func(string, ...interface{})) Option {
+	return func(w *windowsAnsiEventHandler) {
+		w.logf = f
 	}
+}
 
+func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler {
 	infoReset, err := GetConsoleScreenBufferInfo(fd)
 	if err != nil {
 		return nil
 	}
 
-	return &windowsAnsiEventHandler{
+	h := &windowsAnsiEventHandler{
 		fd:         fd,
 		file:       file,
 		infoReset:  infoReset,
 		attributes: infoReset.Attributes,
 	}
+	for _, o := range opts {
+		o(h)
+	}
+
+	if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
+		logFile, _ := os.Create("winEventHandler.log")
+		logger := log.New(logFile, "", log.LstdFlags)
+		if h.logf != nil {
+			l := h.logf
+			h.logf = func(s string, v ...interface{}) {
+				l(s, v...)
+				logger.Printf(s, v...)
+			}
+		} else {
+			h.logf = logger.Printf
+		}
+	}
+
+	if h.logf == nil {
+		h.logf = func(string, ...interface{}) {}
+	}
+
+	return h
 }
 
 type scrollRegion struct {
@@ -96,7 +113,7 @@ func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) {
 		if err := h.Flush(); err != nil {
 			return false, err
 		}
-		logger.Info("Simulating LF inside scroll region")
+		h.logf("Simulating LF inside scroll region")
 		if err := h.scrollUp(1); err != nil {
 			return false, err
 		}
@@ -119,7 +136,7 @@ func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) {
 	} else {
 		// The cursor is at the bottom of the screen but outside the scroll
 		// region. Skip the LF.
-		logger.Info("Simulating LF outside scroll region")
+		h.logf("Simulating LF outside scroll region")
 		if includeCR {
 			if err := h.Flush(); err != nil {
 				return false, err
@@ -151,7 +168,7 @@ func (h *windowsAnsiEventHandler) executeLF() error {
 			if err := h.Flush(); err != nil {
 				return err
 			}
-			logger.Info("Resetting cursor position for LF without CR")
+			h.logf("Resetting cursor position for LF without CR")
 			if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
 				return err
 			}
@@ -186,7 +203,7 @@ func (h *windowsAnsiEventHandler) Print(b byte) error {
 func (h *windowsAnsiEventHandler) Execute(b byte) error {
 	switch b {
 	case ansiterm.ANSI_TAB:
-		logger.Info("Execute(TAB)")
+		h.logf("Execute(TAB)")
 		// Move to the next tab stop, but preserve auto-wrap if already set.
 		if !h.wrapNext {
 			pos, info, err := h.getCurrentInfo()
@@ -269,7 +286,7 @@ func (h *windowsAnsiEventHandler) CUU(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CUU: [%v]", []string{strconv.Itoa(param)})
+	h.logf("CUU: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.moveCursorVertical(-param)
 }
@@ -278,7 +295,7 @@ func (h *windowsAnsiEventHandler) CUD(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CUD: [%v]", []string{strconv.Itoa(param)})
+	h.logf("CUD: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.moveCursorVertical(param)
 }
@@ -287,7 +304,7 @@ func (h *windowsAnsiEventHandler) CUF(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CUF: [%v]", []string{strconv.Itoa(param)})
+	h.logf("CUF: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.moveCursorHorizontal(param)
 }
@@ -296,7 +313,7 @@ func (h *windowsAnsiEventHandler) CUB(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CUB: [%v]", []string{strconv.Itoa(param)})
+	h.logf("CUB: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.moveCursorHorizontal(-param)
 }
@@ -305,7 +322,7 @@ func (h *windowsAnsiEventHandler) CNL(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CNL: [%v]", []string{strconv.Itoa(param)})
+	h.logf("CNL: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.moveCursorLine(param)
 }
@@ -314,7 +331,7 @@ func (h *windowsAnsiEventHandler) CPL(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CPL: [%v]", []string{strconv.Itoa(param)})
+	h.logf("CPL: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.moveCursorLine(-param)
 }
@@ -323,7 +340,7 @@ func (h *windowsAnsiEventHandler) CHA(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CHA: [%v]", []string{strconv.Itoa(param)})
+	h.logf("CHA: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.moveCursorColumn(param)
 }
@@ -332,7 +349,7 @@ func (h *windowsAnsiEventHandler) VPA(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("VPA: [[%d]]", param)
+	h.logf("VPA: [[%d]]", param)
 	h.clearWrap()
 	info, err := GetConsoleScreenBufferInfo(h.fd)
 	if err != nil {
@@ -348,7 +365,7 @@ func (h *windowsAnsiEventHandler) CUP(row int, col int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("CUP: [[%d %d]]", row, col)
+	h.logf("CUP: [[%d %d]]", row, col)
 	h.clearWrap()
 	info, err := GetConsoleScreenBufferInfo(h.fd)
 	if err != nil {
@@ -364,7 +381,7 @@ func (h *windowsAnsiEventHandler) HVP(row int, col int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("HVP: [[%d %d]]", row, col)
+	h.logf("HVP: [[%d %d]]", row, col)
 	h.clearWrap()
 	return h.CUP(row, col)
 }
@@ -373,7 +390,7 @@ func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("DECTCEM: [%v]", []string{strconv.FormatBool(visible)})
+	h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)})
 	h.clearWrap()
 	return nil
 }
@@ -382,7 +399,7 @@ func (h *windowsAnsiEventHandler) DECOM(enable bool) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("DECOM: [%v]", []string{strconv.FormatBool(enable)})
+	h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)})
 	h.clearWrap()
 	h.originMode = enable
 	return h.CUP(1, 1)
@@ -392,7 +409,7 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("DECCOLM: [%v]", []string{strconv.FormatBool(use132)})
+	h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)})
 	h.clearWrap()
 	if err := h.ED(2); err != nil {
 		return err
@@ -407,7 +424,7 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
 	}
 	if info.Size.X < targetWidth {
 		if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
-			logger.Info("set buffer failed:", err)
+			h.logf("set buffer failed: %v", err)
 			return err
 		}
 	}
@@ -415,12 +432,12 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
 	window.Left = 0
 	window.Right = targetWidth - 1
 	if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
-		logger.Info("set window failed:", err)
+		h.logf("set window failed: %v", err)
 		return err
 	}
 	if info.Size.X > targetWidth {
 		if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
-			logger.Info("set buffer failed:", err)
+			h.logf("set buffer failed: %v", err)
 			return err
 		}
 	}
@@ -431,7 +448,7 @@ func (h *windowsAnsiEventHandler) ED(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("ED: [%v]", []string{strconv.Itoa(param)})
+	h.logf("ED: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 
 	// [J  -- Erases from the cursor to the end of the screen, including the cursor position.
@@ -490,7 +507,7 @@ func (h *windowsAnsiEventHandler) EL(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("EL: [%v]", strconv.Itoa(param))
+	h.logf("EL: [%v]", strconv.Itoa(param))
 	h.clearWrap()
 
 	// [K  -- Erases from the cursor to the end of the line, including the cursor position.
@@ -531,7 +548,7 @@ func (h *windowsAnsiEventHandler) IL(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("IL: [%v]", strconv.Itoa(param))
+	h.logf("IL: [%v]", strconv.Itoa(param))
 	h.clearWrap()
 	return h.insertLines(param)
 }
@@ -540,7 +557,7 @@ func (h *windowsAnsiEventHandler) DL(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("DL: [%v]", strconv.Itoa(param))
+	h.logf("DL: [%v]", strconv.Itoa(param))
 	h.clearWrap()
 	return h.deleteLines(param)
 }
@@ -549,7 +566,7 @@ func (h *windowsAnsiEventHandler) ICH(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("ICH: [%v]", strconv.Itoa(param))
+	h.logf("ICH: [%v]", strconv.Itoa(param))
 	h.clearWrap()
 	return h.insertCharacters(param)
 }
@@ -558,7 +575,7 @@ func (h *windowsAnsiEventHandler) DCH(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("DCH: [%v]", strconv.Itoa(param))
+	h.logf("DCH: [%v]", strconv.Itoa(param))
 	h.clearWrap()
 	return h.deleteCharacters(param)
 }
@@ -572,7 +589,7 @@ func (h *windowsAnsiEventHandler) SGR(params []int) error {
 		strings = append(strings, strconv.Itoa(v))
 	}
 
-	logger.Infof("SGR: [%v]", strings)
+	h.logf("SGR: [%v]", strings)
 
 	if len(params) <= 0 {
 		h.attributes = h.infoReset.Attributes
@@ -606,7 +623,7 @@ func (h *windowsAnsiEventHandler) SU(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("SU: [%v]", []string{strconv.Itoa(param)})
+	h.logf("SU: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.scrollUp(param)
 }
@@ -615,13 +632,13 @@ func (h *windowsAnsiEventHandler) SD(param int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("SD: [%v]", []string{strconv.Itoa(param)})
+	h.logf("SD: [%v]", []string{strconv.Itoa(param)})
 	h.clearWrap()
 	return h.scrollDown(param)
 }
 
 func (h *windowsAnsiEventHandler) DA(params []string) error {
-	logger.Infof("DA: [%v]", params)
+	h.logf("DA: [%v]", params)
 	// DA cannot be implemented because it must send data on the VT100 input stream,
 	// which is not available to go-ansiterm.
 	return nil
@@ -631,7 +648,7 @@ func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Infof("DECSTBM: [%d, %d]", top, bottom)
+	h.logf("DECSTBM: [%d, %d]", top, bottom)
 
 	// Windows is 0 indexed, Linux is 1 indexed
 	h.sr.top = int16(top - 1)
@@ -646,7 +663,7 @@ func (h *windowsAnsiEventHandler) RI() error {
 	if err := h.Flush(); err != nil {
 		return err
 	}
-	logger.Info("RI: []")
+	h.logf("RI: []")
 	h.clearWrap()
 
 	info, err := GetConsoleScreenBufferInfo(h.fd)
@@ -663,21 +680,21 @@ func (h *windowsAnsiEventHandler) RI() error {
 }
 
 func (h *windowsAnsiEventHandler) IND() error {
-	logger.Info("IND: []")
+	h.logf("IND: []")
 	return h.executeLF()
 }
 
 func (h *windowsAnsiEventHandler) Flush() error {
 	h.curInfo = nil
 	if h.buffer.Len() > 0 {
-		logger.Infof("Flush: [%s]", h.buffer.Bytes())
+		h.logf("Flush: [%s]", h.buffer.Bytes())
 		if _, err := h.buffer.WriteTo(h.file); err != nil {
 			return err
 		}
 	}
 
 	if h.wrapNext && !h.drewMarginByte {
-		logger.Infof("Flush: drawing margin byte '%c'", h.marginByte)
+		h.logf("Flush: drawing margin byte '%c'", h.marginByte)
 
 		info, err := GetConsoleScreenBufferInfo(h.fd)
 		if err != nil {