github.com/cgmcandrews/terraform@v0.11.12-beta1/command/format/diagnostic.go (about)

     1  package format
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/hashicorp/terraform/tfdiags"
     8  	"github.com/mitchellh/colorstring"
     9  	wordwrap "github.com/mitchellh/go-wordwrap"
    10  )
    11  
    12  // Diagnostic formats a single diagnostic message.
    13  //
    14  // The width argument specifies at what column the diagnostic messages will
    15  // be wrapped. If set to zero, messages will not be wrapped by this function
    16  // at all. Although the long-form text parts of the message are wrapped,
    17  // not all aspects of the message are guaranteed to fit within the specified
    18  // terminal width.
    19  func Diagnostic(diag tfdiags.Diagnostic, color *colorstring.Colorize, width int) string {
    20  	if diag == nil {
    21  		// No good reason to pass a nil diagnostic in here...
    22  		return ""
    23  	}
    24  
    25  	var buf bytes.Buffer
    26  
    27  	switch diag.Severity() {
    28  	case tfdiags.Error:
    29  		buf.WriteString(color.Color("\n[bold][red]Error: [reset]"))
    30  	case tfdiags.Warning:
    31  		buf.WriteString(color.Color("\n[bold][yellow]Warning: [reset]"))
    32  	default:
    33  		// Clear out any coloring that might be applied by Terraform's UI helper,
    34  		// so our result is not context-sensitive.
    35  		buf.WriteString(color.Color("\n[reset]"))
    36  	}
    37  
    38  	desc := diag.Description()
    39  	sourceRefs := diag.Source()
    40  
    41  	// We don't wrap the summary, since we expect it to be terse, and since
    42  	// this is where we put the text of a native Go error it may not always
    43  	// be pure text that lends itself well to word-wrapping.
    44  	if sourceRefs.Subject != nil {
    45  		fmt.Fprintf(&buf, color.Color("[bold]%s[reset] at %s\n\n"), desc.Summary, sourceRefs.Subject.StartString())
    46  	} else {
    47  		fmt.Fprintf(&buf, color.Color("[bold]%s[reset]\n\n"), desc.Summary)
    48  	}
    49  
    50  	// TODO: also print out the relevant snippet of config source with the
    51  	// relevant section highlighted, so the user doesn't need to manually
    52  	// correlate back to config. Before we can do this, the HCL2 parser
    53  	// needs to be more deeply integrated so that we can use it to obtain
    54  	// the parsed source code and AST.
    55  
    56  	if desc.Detail != "" {
    57  		detail := desc.Detail
    58  		if width != 0 {
    59  			detail = wordwrap.WrapString(detail, uint(width))
    60  		}
    61  		fmt.Fprintf(&buf, "%s\n", detail)
    62  	}
    63  
    64  	return buf.String()
    65  }