github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/cmd/internal/cli/output.go (about)

     1  /*
     2   * Copyright (c) 2018-2020 vChain, Inc. All Rights Reserved.
     3   * This software is released under GPL3.
     4   * The full license information can be found under:
     5   * https://www.gnu.org/licenses/gpl-3.0.en.html
     6   *
     7   */
     8  
     9  package cli
    10  
    11  import (
    12  	"encoding/json"
    13  	"fmt"
    14  	"io"
    15  	"os"
    16  	"reflect"
    17  	"strings"
    18  	"text/tabwriter"
    19  
    20  	"github.com/fatih/color"
    21  	"github.com/mattn/go-colorable"
    22  
    23  	"gopkg.in/yaml.v2"
    24  
    25  	"github.com/dustin/go-humanize"
    26  	"github.com/vchain-us/vcn/pkg/api"
    27  	"github.com/vchain-us/vcn/pkg/cmd/internal/types"
    28  	"github.com/vchain-us/vcn/pkg/meta"
    29  )
    30  
    31  func WriteResultTo(r *types.Result, out io.Writer) (n int64, err error) {
    32  	if r == nil {
    33  		return 0, nil
    34  	}
    35  
    36  	w := new(tabwriter.Writer)
    37  	w.Init(out, 0, 8, 0, '\t', 0)
    38  
    39  	printf := func(format string, a ...interface{}) error {
    40  		m, err := fmt.Fprintf(w, format, a...)
    41  		n += int64(m)
    42  		return err
    43  	}
    44  
    45  	s := reflect.ValueOf(r).Elem()
    46  	s = s.FieldByName("ArtifactResponse")
    47  	typeOfT := s.Type()
    48  
    49  	for i, l := 0, s.NumField(); i < l; i++ {
    50  		f := s.Field(i)
    51  		if key, ok := typeOfT.Field(i).Tag.Lookup("vcn"); ok {
    52  			var value string
    53  			switch key {
    54  			case "Size":
    55  				if size, ok := f.Interface().(uint64); ok && size > 0 {
    56  					value = humanize.Bytes(size)
    57  				}
    58  			case "Metadata":
    59  				if metadata, ok := f.Interface().(api.Metadata); ok {
    60  					for k, v := range metadata {
    61  						if v == "" {
    62  							continue
    63  						}
    64  						if vv, err := json.MarshalIndent(v, "\t", "    "); err == nil {
    65  							value += fmt.Sprintf("\n\t\t%s=%s", k, string(vv))
    66  						}
    67  					}
    68  					value = strings.TrimPrefix(value, "\n")
    69  				}
    70  			case "Signer":
    71  				// todo(leogr): this will not happen anymore with the new platform APIs.
    72  				// Still retained to accommodate future improvements.
    73  				if f.Interface() != r.Verification.SignerID() {
    74  					value = fmt.Sprintf("%s", f.Interface())
    75  				}
    76  			default:
    77  				value = fmt.Sprintf("%s", f.Interface())
    78  			}
    79  			if value != "" {
    80  				err = printf("%s:\t%s\n", key, value)
    81  				if err != nil {
    82  					return
    83  				}
    84  			}
    85  		}
    86  	}
    87  
    88  	if bv := r.Verification; bv != nil {
    89  		if key := bv.SignerID(); key != "" {
    90  			err = printf("SignerID:\t%s\n", bv.SignerID())
    91  			if err != nil {
    92  				return
    93  			}
    94  		}
    95  		if bv.Level != 0 {
    96  			err = printf("Level:\t%s\n", bv.Level.String())
    97  			if err != nil {
    98  				return
    99  			}
   100  		}
   101  		if date := bv.Date(); date != "" {
   102  			err = printf("Date:\t%s\n", date)
   103  			if err != nil {
   104  				return
   105  			}
   106  		}
   107  		err = printf("Status:\t%s\n", meta.StatusNameStyled(r.Verification.Status))
   108  		if err != nil {
   109  			return
   110  		}
   111  	}
   112  
   113  	for _, e := range r.Errors {
   114  		err = printf("Error:\t%s\n", color.New(meta.StyleError()).Sprintf(e.Error()))
   115  		if err != nil {
   116  			return
   117  		}
   118  	}
   119  
   120  	return n, w.Flush()
   121  }
   122  
   123  func Print(output string, r *types.Result) error {
   124  	switch output {
   125  	case "", "attachments":
   126  		WriteResultTo(r, colorable.NewColorableStdout())
   127  	case "yaml":
   128  		b, err := yaml.Marshal(r)
   129  		if err != nil {
   130  			return err
   131  		}
   132  		fmt.Println(string(b))
   133  	case "json":
   134  		b, err := json.MarshalIndent(r, "", "  ")
   135  		if err != nil {
   136  			return err
   137  		}
   138  		fmt.Println(string(b))
   139  	default:
   140  		return outputNotSupportedErr(output)
   141  	}
   142  	return nil
   143  }
   144  
   145  func PrintSlice(output string, rs []types.Result) error {
   146  	switch output {
   147  	case "", "attachments":
   148  		for _, r := range rs {
   149  			WriteResultTo(&r, colorable.NewColorableStdout())
   150  			fmt.Println()
   151  		}
   152  	case "yaml":
   153  		b, err := yaml.Marshal(rs)
   154  		if err != nil {
   155  			return err
   156  		}
   157  		fmt.Println(string(b))
   158  	case "json":
   159  		b, err := json.MarshalIndent(rs, "", "  ")
   160  		if err != nil {
   161  			return err
   162  		}
   163  		fmt.Println(string(b))
   164  	default:
   165  		return outputNotSupportedErr(output)
   166  	}
   167  	return nil
   168  }
   169  
   170  func PrintList(output string, artifacts []api.ArtifactResponse) error {
   171  	switch output {
   172  	case "", "attachments":
   173  		for _, a := range artifacts {
   174  			fmt.Print(a)
   175  		}
   176  	case "yaml":
   177  		b, err := yaml.Marshal(artifacts)
   178  		if err != nil {
   179  			return err
   180  		}
   181  		fmt.Println(string(b))
   182  	case "json":
   183  		b, err := json.MarshalIndent(artifacts, "", "  ")
   184  		if err != nil {
   185  			return err
   186  		}
   187  		fmt.Println(string(b))
   188  	default:
   189  		return outputNotSupportedErr(output)
   190  	}
   191  	return nil
   192  }
   193  
   194  func PrintError(output string, err *types.Error) error {
   195  	if err == nil {
   196  		return nil
   197  	}
   198  	switch output {
   199  	case "", "attachments":
   200  		fmt.Fprintf(os.Stderr, "\nError: %s\n", err)
   201  	case "yaml":
   202  		b, err := yaml.Marshal(err)
   203  		if err != nil {
   204  			return err
   205  		}
   206  		fmt.Println(string(b))
   207  	case "json":
   208  		b, err := json.MarshalIndent(err, "", "  ")
   209  		if err != nil {
   210  			return err
   211  		}
   212  		fmt.Println(string(b))
   213  	default:
   214  		return outputNotSupportedErr(output)
   215  	}
   216  	return nil
   217  }
   218  
   219  func PrintWarning(output string, message string) error {
   220  	switch output {
   221  	case "", "attachments":
   222  		fallthrough
   223  	case "yaml":
   224  		fallthrough
   225  	case "json":
   226  		fmt.Fprintf(os.Stderr, "\nWarning: %s\n", message)
   227  	default:
   228  		return outputNotSupportedErr(output)
   229  	}
   230  	return nil
   231  }
   232  
   233  func outputNotSupportedErr(output string) error {
   234  	return fmt.Errorf("output format not supported: %s", output)
   235  }
   236  
   237  func PrintObjects(output string, out interface{}) error {
   238  	switch output {
   239  	case "", "attachments":
   240  		fallthrough
   241  	case "yaml":
   242  		b, err := yaml.Marshal(out)
   243  		if err != nil {
   244  			return err
   245  		}
   246  		fmt.Println(string(b))
   247  	case "json":
   248  		b, err := json.MarshalIndent(out, "", "  ")
   249  		if err != nil {
   250  			return err
   251  		}
   252  		fmt.Println(string(b))
   253  	default:
   254  		return outputNotSupportedErr(output)
   255  	}
   256  	return nil
   257  }