!yuE8      !"#$%&'()*+,-./01234567Safe"89:;<=>?SafeDvformat)ArgKey indicates a key of format argumentThere are two kinds of basic key, named and indexed, and a composed key indicates a key which is a attribute of an argument.4When read from a String, the sytax is as followings: 1if all chars are digits, it means an indexed key,if there is a "!"/, it means a nested key, the chars before "!"7 is parent key, and the chars after are child key,if you want to use literal "!"- in the key, you can write it doublely, "!!",.if there are not all digits, it's a named key. Examples:read "country" :: ArgKeyName "country"read "123" :: ArgKey Index 123read "country!name" :: ArgKey#Nest (Name "country") (Name "name")"read "country!cities!10" :: ArgKey7Nest (Name "country") (Nest (Name "cities") (Index 10))read "coun!!try" :: ArgKeyName "coun!try"SafeUVvformat3A type represent a named ArgKey and an another data 66SafeE vformat&Description of argument format options/When read from string, the sytax is as follows: =[[pad]align][sign][#][0][width][separator][.precision][specs][]) means an optional field (or filed group)pad; means char to be used for padding, it should be a literal @, default is spacealign means align option y < AlignLeft > AlignRight ^ AlignCenter = AlignSign empty AlignNone sign means number sign option ] + SignPlus - SignMinus space SignSpace empty SignNone ## means number alternate form option0 preceding width0 option means sign-aware as well as zero-padding ; number AlignNone & sign aware = AlignSign & pad '0'$ other types means nothing width0 means minimum argument width, it may be an 3 indicates it's value from another integer argument J integer minimum width empty no minimum widht constrain  separator number separator option L _ NumSepDash , NumSepComma empty NumSepNone  precisionX (must leading with a dot) number preceding or maximum with option it may be an 3 indicates it's value from another integer argument t for number (floating point) types number precision for non-number types maximum widht specsq type specified options, it determines how data should be presented, see available type presentions belowString presentions i s explicitly specified string type empty implicitly specified string type Integer presentions H b binary format integer c char point (@ will be trasformed by  first) d decimal format integer o octal format integer x hex format integer (use lower-case letters) X hex format integer (use upper-case letters) empty same as "d" !Floating point number presentions * e exponent notation, see A4 E same as "e", but use upper-case E: as separator f fixed-point notation see Bo F same as "f", but converts nan to NAN and inf to INF g general format, see C4 G same as "g", but use upper-case E as separator and converts nan to NAN and inf to INF % percentage, same as "f" except multiplies 100 first and followed by a percent sign empty same as "g" Examplesread "*<30s" :: ArgFmtread "<10.20s" :: ArgFmtread "0=10_.20d" :: ArgFmtread "#010_.20b" :: ArgFmtvformatNumber separatorvformat don't sepratevformat seprate by '_'vformatseprate by ','vformatHow to show number's signNote:  is equivalent to  for signed numbersvformatsign is not specifiedvformat*show '+' for positive and '-' for negativevformatshow negative's sign onlyvformatshow ' ' for positive and D for negativevformatHow to align argumentNote:   is equivalent to !$ unless number's sign aware enabled vformatalignment is not specified!vformatpad chars before argument"vformatpad chars before argument#vformat#pad chars before and after argument$vformat-number specified, pad between sign and digits   !"#$%&SafeY#'vformat A variant of *', it transforms all argument's key to Nest (Index 0) key*vformatFormat is a list of -hA format contains a variet of literal chars and arguments to be replaced, argument sytax is as follows:  {[key][:fmt]}{}- means it must be wraped in a pair of braces,[]* means an optional field (or field group),key is argument's key, see ,fmt7 (must leading with a colon) is argument's format, see  .hIf you need to include a brace character in the literal text, it can be escaped by doubling: {{ and }}.?if key is ommited, it means an automically positioned argument. Examples:unFormat "a left brace {{"[Lit "a left brace {"]unFormat "hello {}"*[Lit "hello ", Arg (Index 0) (ArgFmt ...)]unFormat "{} {}"8[Arg (Index 0) (ArgFmt ...), Arg (Index 1) (ArgFmt ...)]unFormat "{1} {0}"8[Arg (Index 1) (ArgFmt ...), Arg (Index 0) (ArgFmt ...)]unFormat "{gender} {age}"A[Arg (Name "gender") (ArgFmt ...), Arg (Name "age") (ArgFmt ...)]unFormat "{0!gender}"2[Arg (Nest (Index 0) (Name "gender")) (ArgFmt ..)]unFormat "{:<30s}"I[Arg (Index 0) (ArgFmt { fmtAlgin = AlignLeft, fmtWidth = Left 30, ...})]unFormat "{:<{width}s}"?[Arg (Index 0) (ArgFmt {fmtWidth = Right (Name "width"), ...})] '()*+,-/. Safe8=>?UVh0vformat6A typeclass provides the variable arguments magic for format2vformatTypeclass of formatable values.)Make an instance for your own data types:  data Coffe = Black | Latte | Other deriving Show instance FormatArg Coffe where formatArg x k fmt = formatArg (show x) k fmt   newtype Big a = Big { unBig :: a} instance FormatArg a => FormatArg (Big a) where formatArg (Big x) k fmt = formatArg x k fmt   data Student = Student { name :: String , age :: Int , email :: String } deriving Generic instance FormatArg Student Z data Address = Address { country :: String , city :: String , street :: String } instance FormatArg Address where formatArg x k fmt = formatArg result k fmt where result :: String result = format "{:s},{:s},{:s}" (street x) (city x) (country x) 012345(c) 2019 Version CloudBSD3Jorah Gao <jorah@version.cloud> experimentalportableSafes6vformatHFormat a variable number of argument with Python-style formatting string*format "hello {} {}" "world" "!" :: String hello world !,format "hello {1} {0}" "!" "world" :: String hello world !<format "hello {to} {bang}" ("to" := "world") ("bang" := "!") hello world !7vformat3Format argument with Python-style formatting string:set -XDeriveGenericHdata Greeting = Greeting {to :: String, bang :: String} deriving Genericinstance FormatArg Greeting2format1 "hello {to} {bang}" (Greeting "world" "!") hello world !5format "hello {0!to} {0!bang}" (Greeting "world" "!") hello world !8   !"#$%&'()*+,-/.01234567867523401-/.*+,'() !"#$  %& E     !"#$%&'()*+,-.//0112345 6 7 8 9 : ;<=>?@ABCDEFGHIJHIKHILHMNO&vformat-0.9.0.0-GRDYvdM0oPKJWlsXBfQ6DI Text.Format Paths_vformatText.Format.ArgKeyText.Format.InternalText.Format.ArgFmtCharordText.Format.FormatText.Format.ClassArgKeyIndexNameNest:=ferror errorArgFmt errorCloseTag errorTypeFmterrorMissingArgArgFmtfmtAlignfmtPadfmtSign fmtAlternate fmtSignAwarefmtWidth fmtNumSep fmtPrecisionfmtSpecs FmtNumSep NumSepNone NumSepDash NumSepCommaFmtSignSignNoneSignPlus SignMinus SignSpaceFmtAlign AlignNone AlignLeft AlignRight AlignCenter AlignSign formatText formatNumberFormat1 unFormat1FormatunFormatFmtItemLitArg FormatTypesfmt FormatArg formatArgkeyOf Formatterformatformat1version getBinDir getLibDir getDynLibDir getDataDir getLibexecDir getSysconfDirgetDataFileNameghc-prim GHC.TypesbaseNumeric showEFloat showFFloat showGFloatGHC.Num-