github.com/decred/politeia@v1.4.0/politeiawww/cmd/pictl/print.go (about) 1 // Copyright (c) 2020-2021 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "strconv" 11 "strings" 12 13 "github.com/decred/politeia/util" 14 ) 15 16 // printf prints the provided string to stdout if the global config settings 17 // allows for it. 18 func printf(s string, args ...interface{}) { 19 switch { 20 case cfg.Verbose, cfg.RawJSON: 21 // These are handled by the politeiawwww client 22 case cfg.Silent: 23 // Do nothing 24 default: 25 // Print to stdout 26 fmt.Printf(s, args...) 27 } 28 } 29 30 // printJSON pretty prints the provided structure if the global config settings 31 // allow for it. 32 func printJSON(v interface{}) { 33 printf("%v\n", util.FormatJSON(v)) 34 } 35 36 // printInPlace prints the provided text to stdout in a way that overwrites the 37 // existing stdout text. This function can be called multiple times. Each 38 // subsequent call will overwrite the existing text that was printed to stdout. 39 func printInPlace(s string) { 40 fmt.Printf("\033[2K\r%s", s) 41 } 42 43 // addIndent adds indentation to the beginning of each line of the provided 44 // string. The indentInSpaces argument is the number of spaces that will be 45 // inserted into each line. 46 // 47 // Example: addIndent("hello,\nworld!\n", 2) -> " hello,\n world!\n" 48 func addIndent(s string, indentInSpaces uint) string { 49 // Setup indent string 50 var b strings.Builder 51 for i := 0; i < int(indentInSpaces); i++ { 52 b.WriteString(" ") 53 } 54 indent := b.String() 55 56 // Add indentation after each new line 57 r := strings.NewReplacer("\n", "\n"+indent) 58 ss := r.Replace(s) 59 60 // Remove trailing spaces 61 ss = strings.TrimSpace(ss) 62 63 // Add indent to the first line 64 return indent + ss 65 } 66 67 // byteCountSI converts the provided bytes to a string representation of the 68 // closest SI unit (kB, MB, GB, etc). 69 func byteCountSI(b int64) string { 70 const unit = 1000 71 if b < unit { 72 return fmt.Sprintf("%d B", b) 73 } 74 div, exp := int64(unit), 0 75 for n := b / unit; n >= unit; n /= unit { 76 div *= unit 77 exp++ 78 } 79 return fmt.Sprintf("%.1f %cB", 80 float64(b)/float64(div), "kMGTPE"[exp]) 81 } 82 83 // dollars converts an int64 price in cents into a human readable dollar 84 // string. 85 // 86 // | Input | Output | 87 // |-----------------------------| 88 // | 130000000 | "$1,300,000.00" | 89 // | 13000000 | "$130,000.00" | 90 // | 130000 | "$1,300.00" | 91 // | 13000 | "$130.00" | 92 // | 78 | "$0.78" | 93 // | 9 | "$0.09" | 94 // | 0 | "$0.00" | 95 // | -9 | "-$0.09" | 96 // | -78 | "-$0.78" | 97 // | -13000000 | "-$130,000.00" | 98 func dollars(cents int64) string { 99 // Get the value in dollars. 100 dollars := float64(cents) / 100 101 102 // Initialize the buffer to store the string result. 103 var buf bytes.Buffer 104 105 // Check for a negative value. 106 if dollars < 0 { 107 buf.WriteString("-") 108 // Convert the negative value to a positive value. 109 // The code below can only handle positive values. 110 dollars = 0 - dollars 111 } 112 buf.WriteString("$") 113 114 // Convert the dollar value into a string and split it into a 115 // integer and decimal. This is done so that commas can be added 116 // to the integer. 117 var ( 118 f = strconv.FormatFloat(dollars, 'f', -1, 64) 119 s = strings.Split(f, ".") 120 integer = s[0] 121 122 // The value may or may not have a decimal. Default to 0. 123 decimal = ".00" 124 ) 125 if len(s) > 1 { 126 // The value includes a decimal. Overwrite the default. 127 decimal = "." + s[1] 128 } 129 130 // Write the integer to the buffer one character at a time. Commas 131 // are inserted in their appropriate places. 132 // 133 // Examples 134 // "100000" to "100,000" 135 // "1000000" to "1,000,000" 136 for i, c := range integer { 137 // A comma should be inserted if the character index is divisible 138 // by 3 when counting from the right side of the string. 139 divByThree := (len(integer)-i)%3 == 0 140 141 // A comma should never be inserted for the first character. 142 // Ex: "100000" should not be ",100,000" 143 if divByThree && i > 0 { 144 buf.WriteString(",") 145 } 146 147 // Write the character to the buffer. 148 buf.WriteRune(c) 149 } 150 151 // Write the decimal to the buffer. 152 buf.WriteString(decimal) 153 154 return buf.String() 155 }