Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support formatting numbers using a external formatter #58

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions asciigraph.go
Original file line number Diff line number Diff line change
@@ -125,21 +125,46 @@ func PlotMany(data [][]float64, options ...Option) string {
precision = 0
}

maxNumLength := len(fmt.Sprintf("%0.*f", precision, maximum))
minNumLength := len(fmt.Sprintf("%0.*f", precision, minimum))
maxWidth := int(math.Max(float64(maxNumLength), float64(minNumLength)))
maxNumLength, minNumLength := 0, math.MaxInt64
var magnitudes []float64

if config.ValueFormatter == nil {
maxNumLength = len(fmt.Sprintf("%0.*f", precision, maximum))
minNumLength = len(fmt.Sprintf("%0.*f", precision, minimum))
}

// axis and labels
// calculate label magnitudes and the length when formatted using the ValueFormatter
for y := intmin2; y < intmax2+1; y++ {
var magnitude float64
if rows > 0 {
magnitude = maximum - (float64(y-intmin2) * interval / float64(rows))
} else {
magnitude = float64(y)
}
magnitudes = append(magnitudes, magnitude)

if config.ValueFormatter != nil {
l := len(config.ValueFormatter(magnitude))
if l > maxNumLength {
maxNumLength = l
}
if l < minNumLength {
minNumLength = l
}
}
}
maxWidth := int(math.Max(float64(maxNumLength), float64(minNumLength)))

// axis and labels reusing the previously calculated magnitudes
for w, magnitude := range magnitudes {
var label string
if config.ValueFormatter == nil {
label = fmt.Sprintf("%*.*f", maxWidth+1, precision, magnitude)
} else {
val := config.ValueFormatter(magnitude)
label = strings.Repeat(" ", maxWidth+1-len(val)) + val
}

label := fmt.Sprintf("%*.*f", maxWidth+1, precision, magnitude)
w := y - intmin2
h := int(math.Max(float64(config.Offset)-float64(len(label)), 0))

plot[w][h].Text = label
13 changes: 13 additions & 0 deletions asciigraph_test.go
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ func TestPlot(t *testing.T) {
opts []Option
expected string
}{

{
[]float64{1, 1, 1, 1, 1},
nil,
@@ -287,6 +288,18 @@ func TestPlot(t *testing.T) {
`
\x1b[94m 1.00\x1b[0m \x1b[32m┤\x1b[0m╶
\x1b[91mcolor test\x1b[0m`},
{
[]float64{70 * 1024 * 1024 * 1024, 90 * 1024 * 1024 * 1024, 80 * 1024 * 1024 * 1024, 2 * 1024 * 1024 * 1024},
[]Option{Height(5), Width(45), ValueFormatter(func(v float64) string {
return fmt.Sprintf("%.2f Foo", v/1024/1024/1024)
})},
` 89.77 Foo ┤ ╭──────────────────────╮
72.22 Foo ┼──────╯ ╰──╮
54.66 Foo ┤ ╰───╮
37.11 Foo ┤ ╰──╮
19.55 Foo ┤ ╰──╮
2.00 Foo ┤ ╰─`,
},
}

for i := range cases {
10 changes: 10 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
@@ -21,8 +21,11 @@ type config struct {
LabelColor AnsiColor
SeriesColors []AnsiColor
SeriesLegends []string
ValueFormatter NumberFormatter
}

type NumberFormatter func(float64) string

// An optionFunc applies an option.
type optionFunc func(*config)

@@ -124,3 +127,10 @@ func SeriesLegends(text ...string) Option {
c.SeriesLegends = text
})
}

// ValueFormatter formats values printed to the side of graphs
func ValueFormatter(f NumberFormatter) Option {
return optionFunc(func(c *config) {
c.ValueFormatter = f
})
}
1 change: 0 additions & 1 deletion utils.go
Original file line number Diff line number Diff line change
@@ -52,7 +52,6 @@ func linearInterpolate(before, after, atPoint float64) float64 {
}

func interpolateArray(data []float64, fitCount int) []float64 {

var interpolatedData []float64

springFactor := float64(len(data)-1) / float64(fitCount-1)