percent-format-0.0.1: simple printf-style string formatting

Copyright(c) 2016-2018 Rudy Matela
License3-Clause BSD (see the file LICENSE)
MaintainerRudy Matela <rudy@matela.com.br>
Safe HaskellSafe
LanguageHaskell2010

Text.PercentFormat

Description

The Text.PercentFormat library provides printf-style string formatting. It provides a % operator (as in Ruby or Python) and uses the old C-printf-style format you know and love.

This library differs from Text.Printf in that it does not rely on custom typeclasses -- it works on anything that is a Show instance that produces output in the supported formats.

Formatting one value with -%:

> "Hello %s!" -% "World"
"Hello World!"

Formatting three values, tuple style, with -%%%:

> "load average: %1.2f %1.2f %1.2f" -%%% (0.00, 0.066, 0.11)
"load average: 0.00 0.07 0.11"

Formatting three values, chain style, with % and -%:

> "load average: %1.2f %1.2f %1.2f" % 0.00 % 0.066 -% 0.11
"load average: 0.00 0.07 0.11"

To produce a string with a percent sign (%), use two percent signs (%%):

> "memory usage: %i%%" -% 13
"memory usage: 13%"

Percent signs are duplicated when using the % operator to allow chaining (further formats):

> "percent sign: %s, memory usage: %i%%" % "%" % 87
"percent sign: %%, memory usage: 87%%"

Always use the -% operator when formatting the last value to remove duplicate % signs:

> "percent sign: %s, memory usage: %i%%" % "%" -% 87
"percent sign: %, memory usage: 87%"

To print, just prefix you format expression with "putStrLn $":

> putStrLn $ "Hello %s!" -% "World"
Hello World!

Supported formats

  • r -- show representation as-is (including quotes for strings).

    > "%r" % "string"
    "\"string\""
    > "%r" % Just 10
    "Just 10"
  • s -- string. If the argument is showed as a String, intersperse it, otherwise include representation in whole.

    > "%s" % "string"
    "string"
    > "%s" % 10
    "10"
    > "%s" % Just "string"
    "Just \"string\""
  • c -- Argument is converted to a single character. Accepts arguments that when showed are represented as Chars.

    > "%c" % 'a'
    "a"
  • i -- Argument is converted to the nearest decimal integer. Accepts arguments that when showed are represented as either Integers, Rationals or Doubles.

    > "%i" % 5040
    5040
    > "%i" % 3.141
    3
  • d -- Argument is converted to a decimal integer. Accepts arguments that when showed are represented as either Integers, Rationals or Doubles.

    > "%d" % 5040
    5040
    > "%i" % 3.141
    3.141
  • x -- Argument is converted to hexadecimal format with lowercase letters. Accepts arguments that when showed are represented as either Integers, Rationals or Doubles.

    > "%x" % 5040
    "13b0"

    Differently from C's printf, negative integers are printed prefixed with a minus (-) sign:

    > "%x" % (-5040)
    "-13b0"

    Differently from C's printf, this library is able to show hexadecimal fractional parts:

    > "%.6x" % pi
    "3.243f6b"
  • X -- Argument is converted to hexadecimal format with capital letters. Accepts arguments that when showed are represented as either Integers, Rationals or Doubles.

    > "%X" % 5040
    "13B0"
  • o -- Argument is converted to octal format. Accepts arguments that when showed are represented as either Integers, Rationals or Doubles.

    > "%o" % 5040
    "11660"
    > "%.6o" % pi
    "3.110376"
  • b -- Argument is converted to binary format. Accepts arguments that when showed are represented as either Integers, Rationals or Doubles.

    > "%b" % 5040
    "1001110110000"
    > "%.6b" % pi
    "11.001001"
  • f -- Argument is converted to decimal format with a fractional part (even when the given argument is an integer). Accepts arguments that when showed are represented as either Integers, Rationals or Doubles.

    > "%f" % 5040
    "5040.0"
    > "%f" % pi
    "3.141592653589793"
  • e -- Argument is converted to scientific notation. This does not work yet. To be added in a future version.
  • q -- Argument is converted to a rational number. This does not work yet. To be added in a future version.

Supported flag charaters

  • 0 -- the numeric value should be padded by zeros.

    > "%08i" % 5040
    "00005040"
  • - -- left adjusted values.

    > "%-8i" % 5040
    "5040    "
  • -- leave a blank before a positive number.

    > "% i" % 5040
    " 5040"
    > "% i" % (-5040)
    "-5040"
  • + -- leave a plus sign before a positive number.

    > "%+i" % 5040
    "+5040"
    > "%+i" % (-5040)
    "-5040"
  • [1-9][0-9]* -- minimum field width.

    > "%8i" % 5040
    "    5040"
  • .[0-9][0-9]* -- precision.

    > "%.2i" % 5040
    "5040.00"
    > "%9.2i" % 5040
    "  5040.00"

How does it work?

Text.PercentFormat works on values that are Show instances producing results in the expected format. Take for example the following number type:

data Digit = Zero | One | Two | Three
instance Show Digit where
  show Zero   =  "0"
  show One    =  "1"
  show Two    =  "2"
  show Three  =  "3"

Text.PercentFormat works fine on it:

> "%d %i %f %.2f" Zero One Two Three
"0 1 2 3.00"

Because when showed, values of this Digit type are represented as Integers.

Error Handling

This library is designed to avoid raising errors. If conversion cannot be performed an exclamation mark (!) is produced. If there are missing format strings an interrogation mark (?) is produced. For example:

> "%d %d" -% "Ten"
"! ?"

The only two instances where errors are raised are:

  1. the argument values contain errors themselves:

    > "Hello %s!" % error "err"
    *** Exception err
    > error "err" % "World"
    *** Exception err
  2. the format string is not supported:

    > "%j" % 10
    *** Exception: unknown format string `j'

Known bugs

  • "%x" % 3.1415926 takes too long to run.
  • "%x" % pi takes very very long to run.
Synopsis

Documentation

(%) :: Show a => String -> a -> String infixl 9 Source #

Formats a single value into a string without finalizing: leaving duplicate percent signs & remaining format sequences.

> "Hello %s!" % "World"
"Hello World!"
> "processor usage: %d%%" % 67
"processor usage: 67%%"
> "load avg: %.2f %.2f %.2f" % 0.666
"load avg: %0.67 %.2f %.2f"

Please use -% when formatting the last value into a string so that duplicate percent signs are removed.

(-%) :: Show a => String -> a -> String infixl 9 Source #

Formats the last value into a string. This finalizes formatting, removing duplicate percent signs and replacing remaining format sequences with interrogation marks.

> "Hello %s!" -% "World"
"Hello World!"
> "processor usage: %d%%" -% 67
"processor usage: 67%"
> "load avg: %.2f %.2f %.2f" % 0.666
"load avg: %0.67 ? ?"

Please use % if you intend to further format values (chaining).

(/%) :: String -> Char -> String Source #

Replaces "%%" by "%". Any remaining occurrences of format strings are replaced by the given error character. Field width is respected when possible.

> "100%% %i" /% '?'
"100% ?"
> "100%% %03i" /% '?'
"100% ???"

(%%) :: (Show a, Show b) => String -> (a, b) -> String Source #

Formats two values into a string without finalizing: leaving duplicate percent signs & remaining format sequences.

> "%s %s!" %% ("Hello","World")
"Hello World!"
> "load avg: %.2f %.2f %.2f" %% (0.666,0.333)
"load avg: %0.67 %0.33 %.2f"

In general:

s %% (x,y) == s % x % y

Please use -%% if you don't intend to format values into a string any further.

(%%%) :: (Show a, Show b, Show c) => String -> (a, b, c) -> String Source #

Formats three values into a string without finalizing.

> "load avg: %.2f %.2f %.2f" %%% (0.666,0.333,0.1)
"load avg: %0.67 %0.33 %0.10"

(%%%%) :: (Show a, Show b, Show c, Show d) => String -> (a, b, c, d) -> String Source #

Formats four values into a string without finalizing.

(%%%%%) :: (Show a, Show b, Show c, Show d, Show e) => String -> (a, b, c, d, e) -> String Source #

Formats five values into a string without finalizing.

(%%%%%%) :: (Show a, Show b, Show c, Show d, Show e, Show f) => String -> (a, b, c, d, e, f) -> String Source #

Formats six values into a string without finalizing.

(-%%) :: (Show a, Show b) => String -> (a, b) -> String Source #

Formats two values into a string and finalizes it: removing duplicate percent signs & replacing remaining format sequences with interrogation marks.

> "%s %s!" -%% ("Hello","World")
"Hello World!"
> "load avg: %.2f %.2f %.2f" -%% (0.666,0.333)
"load avg: %0.67 %0.33 ?"

In general:

s -%% (x,y) == s % x -% y

Please use %% if you intend to further format values.

(-%%%) :: (Show a, Show b, Show c) => String -> (a, b, c) -> String Source #

Formats three values into a string and finalizes it.

> "load avg: %.2f %.2f %.2f" -%%% (0.666,0.333,0.1)
"load avg: %0.67 %0.33 %0.10"

(-%%%%) :: (Show a, Show b, Show c, Show d) => String -> (a, b, c, d) -> String Source #

Formats four values into a string and finalizes it.

(-%%%%%) :: (Show a, Show b, Show c, Show d, Show e) => String -> (a, b, c, d, e) -> String Source #

Formats five values into a string and finalizes it.

(-%%%%%%) :: (Show a, Show b, Show c, Show d, Show e, Show f) => String -> (a, b, c, d, e, f) -> String Source #

Formats six values into a stirng and finalizes it.

(+%) :: Show a => String -> a -> String Source #

Just an alias to % for use whenever Data.Ratio is in scope.

import Data.Ratio
import Text.PercentFormat hiding ((%))
"..." +% 1 -% 2