Skip to content

Commit

Permalink
Support thousands separator in fmtnum
Browse files Browse the repository at this point in the history
  • Loading branch information
johnkerl committed Feb 18, 2024
1 parent f5eaf29 commit fec4d10
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
5 changes: 3 additions & 2 deletions pkg/dsl/cst/builtin_function_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2000,10 +2000,11 @@ Note that NaN has the property that NaN != NaN, so you need 'is_nan(x)' rather t
name: "fmtnum",
class: FUNC_CLASS_CONVERSION,
help: `Convert int/float/bool to string using printf-style format string (https://pkg.go.dev/fmt), e.g.
'$s = fmtnum($n, "%08d")' or '$t = fmtnum($n, "%.6e")'. This function recurses on array and map values.`,
'$s = fmtnum($n, "%08d")' or '$t = fmtnum($n, "%.6e")'. Miller-specific extension: "%_d" for comma-separated thousands. This function recurses on array and map values.`,
binaryFunc: bifs.BIF_fmtnum,
examples: []string{
`$x = fmtnum($x, "%.6f")`,
`$y = fmtnum($x, "%.6f")`,
`$o = fmtnum($n, "%_d")`,
},
},

Expand Down
42 changes: 40 additions & 2 deletions pkg/mlrval/mlrval_format.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"strconv"
"strings"

"golang.org/x/text/message"
)

//----------------------------------------------------------------
Expand Down Expand Up @@ -103,9 +105,13 @@ func newFormatter(
goFormatString = strings.ReplaceAll(goFormatString, "le", "e")
goFormatString = strings.ReplaceAll(goFormatString, "lg", "g")

// MIller 5 and below required C format strings compatible with 64-bit ints
// Miller 5 and below required C format strings compatible with 64-bit ints
// and double-precision floats: e.g. "%08lld" and "%9.6lf". For Miller 6,
// We must still accept these for backward compatibility.
// we must still accept these for backward compatibility.
if strings.HasSuffix(goFormatString, "%_d") {
// Special sub-case of "d"; must be checked first
return newFormatterToSeparatedInt(goFormatString), nil
}
if strings.HasSuffix(goFormatString, "d") {
return newFormatterToInt(goFormatString), nil
}
Expand Down Expand Up @@ -164,6 +170,38 @@ func (formatter *formatterToFloat) FormatFloat(floatValue float64) string {

// ----------------------------------------------------------------

type formatterToSeparatedInt struct {
formatString string
printer *message.Printer
}

func newFormatterToSeparatedInt(goFormatString string) IFormatter {
return &formatterToSeparatedInt{
formatString: "%d",
printer: message.NewPrinter(message.MatchLanguage("en")),
}
}

func (formatter *formatterToSeparatedInt) Format(mv *Mlrval) *Mlrval {
intValue, isInt := mv.GetIntValue()
if isInt {
formatted := formatter.printer.Sprintf(formatter.formatString, intValue)
return TryFromIntString(formatted)
}
floatValue, isFloat := mv.GetFloatValue()
if isFloat {
formatted := formatter.printer.Sprintf(formatter.formatString, int(floatValue))
return TryFromIntString(formatted)
}
return mv
}

func (formatter *formatterToSeparatedInt) FormatFloat(floatValue float64) string {
return formatter.printer.Sprintf(formatter.formatString, int(floatValue))
}

// ----------------------------------------------------------------

type formatterToInt struct {
goFormatString string
}
Expand Down

0 comments on commit fec4d10

Please sign in to comment.