github.com/mitranim/gg@v0.1.17/grepr/grepr.go (about)

     1  /*
     2  Missing feature of the standard library: printing arbitrary inputs as Go code,
     3  with proper spacing and support for multi-line output with indentation. The
     4  name "repr" stands for "representation" and alludes to the Python function with
     5  the same name.
     6  */
     7  package grepr
     8  
     9  import (
    10  	"fmt"
    11  	r "reflect"
    12  	u "unsafe"
    13  
    14  	"github.com/mitranim/gg"
    15  )
    16  
    17  // Default config used by top-level formatting functions in this package.
    18  var ConfDefault = Conf{Indent: gg.Indent}
    19  
    20  // Config that allows formatting of struct zero fields.
    21  var ConfFull = Conf{Indent: gg.Indent, ZeroFields: true}
    22  
    23  /*
    24  Formatting config.
    25  
    26  	* `.Indent` controls indentation. If empty, output is single line.
    27  	* `.ZeroFields`, if set, forces printing of zero fields in structs.
    28  		By default zero fields are skipped.
    29  	* `.Pkg`, if set, indicates the package name to strip from type names.
    30  */
    31  type Conf struct {
    32  	Indent     string
    33  	ZeroFields bool
    34  	Pkg        string
    35  }
    36  
    37  /*
    38  Short for "is single line". If `.Indent` is empty, this is true, and output
    39  is single-line. Otherwise output is multi-line.
    40  */
    41  func (self Conf) IsSingle() bool { return self.Indent == `` }
    42  
    43  // Short for "is multi line". Inverse of `.IsSingle`.
    44  func (self Conf) IsMulti() bool { return self.Indent != `` }
    45  
    46  // Inverse of `.ZeroFields`.
    47  func (self Conf) SkipZeroFields() bool { return !self.ZeroFields }
    48  
    49  // Shortcut for creating a pretty-formatter with this config.
    50  func (self Conf) Fmt() Fmt {
    51  	var buf Fmt
    52  	buf.Conf = self
    53  	return buf
    54  }
    55  
    56  // Short for "formatter".
    57  type Fmt struct {
    58  	Conf
    59  	gg.Buf
    60  	Lvl       int
    61  	ElideType bool
    62  	Visited   gg.Set[u.Pointer]
    63  }
    64  
    65  /*
    66  Similar to `fmt.Sprintf("%#v")` or `gg.GoString`, but more advanced.
    67  Formats the input as Go code, using the config `ConfDefault`, returning
    68  the resulting string.
    69  */
    70  func String[A any](src A) string { return StringIndent(src, 0) }
    71  
    72  /*
    73  Similar to `fmt.Sprintf("%#v")` or `gg.GoString`, but more advanced.
    74  Formats the input as Go code, using the config `ConfDefault`, returning
    75  the resulting bytes.
    76  */
    77  func Bytes[A any](src A) []byte { return BytesIndent(src, 0) }
    78  
    79  /*
    80  Formats the input as Go code, using the given config, returning the
    81  resulting string.
    82  */
    83  func StringC[A any](conf Conf, src A) string { return StringIndentC(conf, src, 0) }
    84  
    85  /*
    86  Formats the input as Go code, using the given config, returning the
    87  resulting bytes.
    88  */
    89  func BytesC[A any](conf Conf, src A) []byte { return BytesIndentC(conf, src, 0) }
    90  
    91  /*
    92  Formats the input as Go code, using the default config with the given
    93  indentation level, returning the resulting string.
    94  */
    95  func StringIndent[A any](src A, lvl int) string {
    96  	return StringIndentC(ConfDefault, src, lvl)
    97  }
    98  
    99  /*
   100  Formats the input as Go code, using the default config with the given
   101  indentation level, returning the resulting bytes.
   102  */
   103  func BytesIndent[A any](src A, lvl int) []byte {
   104  	return BytesIndentC(ConfDefault, src, lvl)
   105  }
   106  
   107  /*
   108  Formats the input as Go code, using the given config with the given indentation
   109  level, returning the resulting string.
   110  */
   111  func StringIndentC[A any](conf Conf, src A, lvl int) string {
   112  	return gg.ToString(BytesIndentC(conf, src, lvl))
   113  }
   114  
   115  /*
   116  Formats the input as Go code, using the given config with the given indentation
   117  level, returning the resulting bytes.
   118  */
   119  func BytesIndentC[A any](conf Conf, src A, lvl int) []byte {
   120  	buf := conf.Fmt()
   121  	buf.Lvl += lvl
   122  	buf.fmtAny(gg.Type[A](), r.ValueOf(gg.AnyNoEscUnsafe(src)))
   123  	return buf.Buf
   124  }
   125  
   126  /*
   127  Shortcut for printing the input as Go code, prefixed with the given description,
   128  using the default config. Handy for debug-printing.
   129  */
   130  func Prn[A any](desc string, src A) { fmt.Println(desc, String(src)) }
   131  
   132  // Shortcut for printing the input as Go code, using the default config.
   133  func Println[A any](src A) { fmt.Println(String(src)) }
   134  
   135  // Shortcut for printing the input as Go code, using the given config.
   136  func PrintlnC[A any](conf Conf, src A) { fmt.Println(StringC(conf, src)) }