File: string.go

package info (click to toggle)
elvish 0.21.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,372 kB
  • sloc: javascript: 236; sh: 130; python: 104; makefile: 88; xml: 9
file content (54 lines) | stat: -rw-r--r-- 1,494 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package vals

import (
	"math"
	"strconv"
	"strings"
)

// Stringer wraps the String method.
type Stringer interface {
	// Stringer converts the receiver to a string.
	String() string
}

// ToString converts a Value to string. It is implemented for the builtin
// float64 and string types, and type satisfying the Stringer interface. It
// falls back to Repr(v).
func ToString(v any) string {
	switch v := v.(type) {
	case int:
		return strconv.Itoa(v)
	case float64:
		return formatFloat64(v)
		// Other number types handled by "case Stringer"
	case string:
		return v
	case Stringer:
		return v.String()
	default:
		return ReprPlain(v)
	}
}

func formatFloat64(f float64) string {
	// Go's 'g' format is not quite ideal for printing floating point numbers;
	// it uses scientific notation too aggressively, and relatively small
	// numbers like 1234567 are printed with scientific notations, something we
	// don't really want.
	//
	// So we use a different algorithm for determining when to use scientific
	// notation. The algorithm is reverse-engineered from Racket's; it may not
	// be a perfect clone but hopefully good enough.
	//
	// See also b.elv.sh/811 for more context.
	s := strconv.FormatFloat(f, 'f', -1, 64)
	noPoint := !strings.ContainsRune(s, '.')
	if (noPoint && len(s) > 14 && s[len(s)-1] == '0') ||
		strings.HasPrefix(s, "0.0000") {
		return strconv.FormatFloat(f, 'e', -1, 64)
	} else if noPoint && !math.IsNaN(f) && !math.IsInf(f, 0) {
		return s + ".0"
	}
	return s
}