You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: outputter.go
    path of file: ./repos/mockery/pkg
    
    the code of the file until where you have to start completion: package pkg

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"go/ast"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"

	"github.com/chigopher/pathlib"
	"github.com/huandu/xstrings"
	"github.com/iancoleman/strcase"
	"github.com/rs/zerolog"

	"github.com/vektra/mockery/v2/pkg/config"
	"github.com/vektra/mockery/v2/pkg/logging"
	"github.com/vektra/mockery/v2/pkg/stackerr"
)

var ErrInfiniteLoop = fmt.Errorf("infinite loop in template variables detected")

// Functions available in the template for manipulating
//
// Since the map and its functions are stateless, it exists as
// a package var rather than being initialized on every call
// in [parseConfigTemplates] and [generator.printTemplate]
var templateFuncMap = template.FuncMap{
	// String inspection and manipulation
	"contains":    strings.Contains,
	"hasPrefix":   strings.HasPrefix,
	"hasSuffix":   strings.HasSuffix,
	"join":        strings.Join,
	"replace":     strings.Replace,
	"replaceAll":  strings.ReplaceAll,
	"split":       strings.Split,
	"splitAfter":  strings.SplitAfter,
	"splitAfterN": strings.SplitAfterN,
	"trim":        strings.Trim,
	"trimLeft":    strings.TrimLeft,
	"trimPrefix":  strings.TrimPrefix,
	"trimRight":   strings.TrimRight,
	"trimSpace":   strings.TrimSpace,
	"trimSuffix":  strings.TrimSuffix,
	"lower":       strings.ToLower,
	"upper
    
func (p *FileOutputStreamProvider) GetWriter(ctx context.Context, iface *Interface) (io.Writer, error, Cleanup) {
	log := zerolog.Ctx(ctx).With().Str(logging.LogKeyInterface, iface.Name).Logger()
	// ctx = log.WithContext(ctx)

	var path string

	caseName := iface.Name
	if p.Case == "underscore" || p.Case == "snake" {
		caseName = p.underscoreCaseName(caseName)
	}

	if p.KeepTree {
		absOriginalDir, err := filepath.Abs(p.KeepTreeOriginalDirectory)
		if err != nil {
			return nil, err, func() error { return nil }
		}
		relativePath := strings.TrimPrefix(
			filepath.Join(filepath.Dir(iface.FileName), p.filename(caseName)),
			absOriginalDir)

		// as it's not possible to import from internal path, we have to replace it in mocks when KeepTree is used
		relativePath = strings.Replace(relativePath, "/internal/", "/internal_/", -1)

		path = filepath.Join(p.BaseDir, relativePath)
		if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
			return nil, err, func() error { return nil }
		}
	} else if p.InPackage {
		path = filepath.Join(filepath.Dir(iface.FileName), p.filename(caseName))
	} else {
		path = filepath.Join(p.BaseDir, p.filename(caseName))
		if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
			return nil, err, func() error { return nil }
		}
	}

	log = log.With().Str(logging.LogKeyPath, path).Logger()

	log.Debug().Msgf("creating writer to file")
	f, err := os.Create(path)
	if err != nil {
		return nil, err, func() error { return nil }
	}

	return f, nil, func() error {
		return f.Close()
	}
}