fmt 0.3.0.0 → 0.4.0.0
raw patch · 5 files changed
+104/−100 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Fmt: (#|) :: (FromBuilder b) => Builder -> Builder -> b
- Fmt: (#||) :: (FromBuilder b) => Builder -> Builder -> b
- Fmt: (|##|) :: (Buildable a, FromBuilder b) => a -> Builder -> b
- Fmt: (|##||) :: (Show a, FromBuilder b) => a -> Builder -> b
- Fmt: (|#) :: (Buildable a, FromBuilder b) => a -> Builder -> b
- Fmt: (||##|) :: (Buildable a, FromBuilder b) => a -> Builder -> b
- Fmt: (||##||) :: (Show a, FromBuilder b) => a -> Builder -> b
- Fmt: (||#) :: (Show a, FromBuilder b) => a -> Builder -> b
+ Fmt: (+|) :: (FromBuilder b) => Builder -> Builder -> b
+ Fmt: (+||) :: (FromBuilder b) => Builder -> Builder -> b
+ Fmt: (|+) :: (Buildable a, FromBuilder b) => a -> Builder -> b
+ Fmt: (|++|) :: (Buildable a, FromBuilder b) => a -> Builder -> b
+ Fmt: (|++||) :: (Show a, FromBuilder b) => a -> Builder -> b
+ Fmt: (||+) :: (Show a, FromBuilder b) => a -> Builder -> b
+ Fmt: (||++|) :: (Buildable a, FromBuilder b) => a -> Builder -> b
+ Fmt: (||++||) :: (Show a, FromBuilder b) => a -> Builder -> b
- Fmt: infixr 1 ||##|
+ Fmt: infixr 1 ||++|
Files
- CHANGELOG.md +4/−0
- bench/Main.hs +5/−5
- fmt.cabal +2/−2
- lib/Fmt.hs +71/−71
- tests/Main.hs +22/−22
CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.4.0.0++* Renamed `#|` and `|#` to `+|` and `|+` because HLint can't handle `#|` and everyone uses HLint apparently.+ # 0.3.0.0 * Added time formatters (see `Fmt.Time`).
bench/Main.hs view
@@ -13,7 +13,7 @@ import qualified Data.Text.Format as TF import Data.Text.Format.Params as TF import qualified Data.Text.Lazy as LT-import Fmt (( #| ), (|#))+import Fmt ((+|), (|+)) import Formatting (Format, formatToString, int, sformat, stext, string, (%)) import Text.Printf (printf)@@ -68,7 +68,7 @@ [ bgroup "simple" [ bTextGroup (1 :: Int, 2 :: Int) [ taggedB "fmt" $- \(a,b) -> "hello "#|a|#" world "#|b|#""+ \(a,b) -> "hello "+|a|+" world "+|b|+"" , taggedB "formatting" $ \(a,b) -> sformat ("hello "%int%" world "%int) a b , taggedB "text-format" $@@ -82,7 +82,7 @@ ] , bStringGroup (1 :: Int, 2 :: Int) [ taggedB "fmt" $- \(a,b) -> "hello "#|a|#" world "#|b|#""+ \(a,b) -> "hello "+|a|+" world "+|b|+"" , taggedB "formatting" $ \(a,b) -> fs ("hello "%int%" world "%int) a b , taggedB "text-format" $@@ -99,7 +99,7 @@ , bgroup "readme" [ bTextGroup (9 :: Int, "Beijing" :: Text) [ taggedB "fmt" $- \(n,city) -> "There are "#|n|#" million bicycles in "#|city|#"."+ \(n,city) -> "There are "+|n|+" million bicycles in "+|city|+"." , taggedB "formatting" $ \(n,city) -> sformat ("There are "%int%" million bicycles in "%stext%".") n city , taggedB "text-format" $@@ -113,7 +113,7 @@ ] , bStringGroup (9 :: Int, "Beijing" :: String) [ taggedB "fmt" $- \(n,city) -> "There are "#|n|#" million bicycles in "#|city|#"."+ \(n,city) -> "There are "+|n|+" million bicycles in "+|city|+"." , taggedB "formatting" $ \(n,city) -> fs ("There are "%int%" million bicycles in "%string%".") n city , taggedB "text-format" $
fmt.cabal view
@@ -1,5 +1,5 @@ name: fmt-version: 0.3.0.0+version: 0.4.0.0 synopsis: A new formatting library description: A new formatting library that tries to be simple to understand while still@@ -46,7 +46,7 @@ maintainer: yom@artyom.me -- copyright: category: Text-tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1+tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1, GHC == 8.2.1 build-type: Simple extra-source-files: CHANGELOG.md cabal-version: >=1.10
lib/Fmt.hs view
@@ -56,18 +56,18 @@ -- ** Ordinary brackets -- $god1- (#|),- (|#),+ (+|),+ (|+), -- ** 'Show' brackets -- $god2- (#||),- (||#),+ (+||),+ (||+), -- ** Combinations -- $god3- (|##|),- (||##||),- (|##||),- (||##|),+ (|++|),+ (||++||),+ (|++||),+ (||++|), -- * Old-style formatting format,@@ -205,12 +205,12 @@ Insert some variables into a string: >>> let (a, b, n) = ("foo", "bar", 25)->>> ("Here are some words: "#|a|#", "#|b|#"\nAlso a number: "#|n|#"") :: String+>>> ("Here are some words: "+|a|+", "+|b|+"\nAlso a number: "+|n|+"") :: String "Here are some words: foo, bar\nAlso a number: 25" Print it: ->>> fmtLn ("Here are some words: "#|a|#", "#|b|#"\nAlso a number: "#|n|#"")+>>> fmtLn ("Here are some words: "+|a|+", "+|b|+"\nAlso a number: "+|n|+"") Here are some words: foo, bar Also a number: 25 @@ -218,16 +218,16 @@ >>> let xs = ["John", "Bob"] ->>> fmtLn ("Using show: "#||xs||#"\nUsing listF: "#|listF xs|#"")+>>> fmtLn ("Using show: "+||xs||+"\nUsing listF: "+|listF xs|+"") Using show: ["John","Bob"] Using listF: [John, Bob] ->>> fmt ("YAML-like:\n"#|blockListF xs|#"")+>>> fmt ("YAML-like:\n"+|blockListF xs|+"") YAML-like: - John - Bob ->>> fmt ("JSON-like: "#|jsonListF xs|#"")+>>> fmt ("JSON-like: "+|jsonListF xs|+"") JSON-like: [ John , Bob@@ -237,13 +237,13 @@ {- $migration -Instead of using @%@, surround variables with '#|' and '|#'. You don't have+Instead of using @%@, surround variables with '+|' and '|+'. You don't have to use @sformat@ or anything else, and also where you were using @build@, @int@, @text@, etc in @formatting@, you don't have to use anything in @fmt@: @ formatting __sformat ("Foo: "%build%", bar: "%int) foo bar__- fmt __"Foo: "\#|foo|\#", bar: "\#|bar|\#""__+ fmt __"Foo: "+|foo|+", bar: "+|bar|+""__ @ The resulting formatted string is polymorphic and can be used as 'String',@@ -256,15 +256,15 @@ @ formatting __sformat ("Got another byte ("%hex%")") x__- fmt __"Got another byte ("\#|hexF x|\#")"__+ fmt __"Got another byte ("+|hexF x|+")"__ @ Instead of the @shown@ formatter, either just use 'show' or double brackets: @ formatting __sformat ("This uses Show: "%shown%") foo__- fmt #1 __"This uses Show: "\#|show foo|\#""__- fmt #2 __"This uses Show: "\#||foo||\#""__+ fmt #1 __"This uses Show: "+|show foo|+""__+ fmt #2 __"This uses Show: "+||foo||+""__ @ Many formatters from @formatting@ have the same names in @fmt@, but with@@ -304,22 +304,22 @@ {- $brackets -To format strings, put variables between ('#|') and ('|#'):+To format strings, put variables between ('+|') and ('|+'): >>> let name = "Alice"->>> "Meet "#|name|#"!" :: String+>>> "Meet "+|name|+"!" :: String "Meet Alice!" Of course, 'Text' is supported as well: ->>> "Meet "#|name|#"!" :: Text+>>> "Meet "+|name|+"!" :: Text "Meet Alice!" You don't actually need any type signatures; however, if you're toying with this library in GHCi, it's recommended to either add a type signature or use 'fmtLn': ->>> fmtLn ("Meet "#|name|#"!")+>>> fmtLn ("Meet "+|name|+"!") Meet Alice! Otherwise the type of the formatted string would be resolved to @IO ()@ and@@ -329,51 +329,51 @@ @ main = do [fin, fout] \<- words \<$\> getArgs- __"Reading data from "\#|fin|\#"\\n"__+ __"Reading data from "+|fin|+"\\n"__ xs \<- readFile fin- __"Writing processed data to "\#|fout|\#"\\n"__+ __"Writing processed data to "+|fout|+"\\n"__ writeFile fout (show (process xs)) @ Anyway, let's proceed. Anything 'Buildable', including numbers, booleans,-characters and dates, can be put between ('#|') and ('|#'):+characters and dates, can be put between ('+|') and ('|+'): >>> let starCount = "173"->>> fmtLn ("Meet "#|name|#"! She's got "#|starCount|#" stars on Github.")+>>> fmtLn ("Meet "+|name|+"! She's got "+|starCount|+" stars on Github.") "Meet Alice! She's got 173 stars on Github." -Since the only thing ('#|') and ('|#') do is concatenate strings and do+Since the only thing ('+|') and ('|+') do is concatenate strings and do conversion, you can use any functions you want inside them. In this case, 'length': ->>> fmtLn (""#|name|#"'s name has "#|length name|#" letters")+>>> fmtLn (""+|name|+"'s name has "+|length name|+" letters") Alice's name has 5 letters If something isn't 'Buildable', just use 'show' on it: >>> let pos = (3, 5)->>> fmtLn ("Character's position: "#|show pos|#"")+>>> fmtLn ("Character's position: "+|show pos|+"") Character's position: (3,5) Or one of many formatters provided by this library – for instance, for tuples of various sizes there's 'tupleF': ->>> fmtLn ("Character's position: "#|tupleF pos|#"")+>>> fmtLn ("Character's position: "+|tupleF pos|+"") Character's position: (3, 5) -Finally, for convenience there's the ('|##|') operator, which can be used if+Finally, for convenience there's the ('|++|') operator, which can be used if you've got one variable following the other: >>> let (a, op, b, res) = (2, "*", 2, 4)->>> fmtLn (""#|a|##|op|##|b|#" = "#|res|#"")+>>> fmtLn (""+|a|++|op|++|b|+" = "+|res|+"") 2*2 = 4 Also, since in some codebases there are /lots/ of types which aren't-'Buildable', there are operators ('#||') and ('||#'), which use 'show'+'Buildable', there are operators ('+||') and ('||+'), which use 'show' instead of 'build': @-__(""\#|show foo|\#\#|show bar|\#"")__ === __(""\#||foo||\#\#||bar||\#"")__+__(""+|show foo|++|show bar|+"")__ === __(""+||foo||++||bar||+"")__ @ -} @@ -381,15 +381,15 @@ -- Operators for the operators god! -- | Concatenate, then convert-(#|) :: (FromBuilder b) => Builder -> Builder -> b-(#|) str rest = fromBuilder (str <> rest)+(+|) :: (FromBuilder b) => Builder -> Builder -> b+(+|) str rest = fromBuilder (str <> rest) -- | 'build' and concatenate, then convert-(|#) :: (Buildable a, FromBuilder b) => a -> Builder -> b-(|#) a rest = fromBuilder (build a <> rest)+(|+) :: (Buildable a, FromBuilder b) => a -> Builder -> b+(|+) a rest = fromBuilder (build a <> rest) -infixr 1 #|-infixr 1 |#+infixr 1 +|+infixr 1 |+ ---------------------------------------------------------------------------- -- Operators with 'Show'@@ -399,17 +399,17 @@ -- More operators for the operators god! -- | Concatenate, then convert-(#||) :: (FromBuilder b) => Builder -> Builder -> b-(#||) str rest = str #| rest-{-# INLINE (#||) #-}+(+||) :: (FromBuilder b) => Builder -> Builder -> b+(+||) str rest = str +| rest+{-# INLINE (+||) #-} -- | 'show' and concatenate, then convert-(||#) :: (Show a, FromBuilder b) => a -> Builder -> b-(||#) a rest = show a |# rest-{-# INLINE (||#) #-}+(||+) :: (Show a, FromBuilder b) => a -> Builder -> b+(||+) a rest = show a |+ rest+{-# INLINE (||+) #-} -infixr 1 #||-infixr 1 ||#+infixr 1 +||+infixr 1 ||+ ---------------------------------------------------------------------------- -- Combinations@@ -419,31 +419,31 @@ Z̸͠A̵̕͟͠L̡̀́͠G̶̛O͝ ̴͏̀ I͞S̸̸̢͠ ̢̛͘͢C̷͟͡Ó̧̨̧͞M̡͘͟͞I̷͜N̷̕G̷̀̕ -(Though you can just use @""@ between @\#| |\#@ instead of using these+(Though you can just use @""@ between @+| |+@ instead of using these operators, and Show-brackets don't have to be used at all because there's 'show' available.) -} -(|##|) :: (Buildable a, FromBuilder b) => a -> Builder -> b-(|##|) a rest = fromBuilder (build a <> rest)-{-# INLINE (|##|) #-}+(|++|) :: (Buildable a, FromBuilder b) => a -> Builder -> b+(|++|) a rest = fromBuilder (build a <> rest)+{-# INLINE (|++|) #-} -(||##||) :: (Show a, FromBuilder b) => a -> Builder -> b-(||##||) a rest = show a |# rest-{-# INLINE (||##||) #-}+(||++||) :: (Show a, FromBuilder b) => a -> Builder -> b+(||++||) a rest = show a |+ rest+{-# INLINE (||++||) #-} -(||##|) :: (Buildable a, FromBuilder b) => a -> Builder -> b-(||##|) a rest = a |##| rest-{-# INLINE (||##|) #-}+(||++|) :: (Buildable a, FromBuilder b) => a -> Builder -> b+(||++|) a rest = a |++| rest+{-# INLINE (||++|) #-} -(|##||) :: (Show a, FromBuilder b) => a -> Builder -> b-(|##||) a rest = a ||##|| rest-{-# INLINE (|##||) #-}+(|++||) :: (Show a, FromBuilder b) => a -> Builder -> b+(|++||) a rest = a ||++|| rest+{-# INLINE (|++||) #-} -infixr 1 |##|-infixr 1 ||##||-infixr 1 ||##|-infixr 1 |##||+infixr 1 |++|+infixr 1 ||++||+infixr 1 ||++|+infixr 1 |++|| ---------------------------------------------------------------------------- -- Old-style formatting@@ -478,8 +478,8 @@ {- | 'fmt' converts things to 'String', 'Text' or 'Builder'. -Most of the time you won't need it, as strings produced with ('#|') and-('|#') can already be used as 'String', 'Text', etc. However, combinators+Most of the time you won't need it, as strings produced with ('+|') and+('|+') can already be used as 'String', 'Text', etc. However, combinators like 'listF' can only produce 'Builder' (for better type inference), and you need to use 'fmt' on them. @@ -1061,14 +1061,14 @@ Display something only if the condition is 'True' (empty string otherwise). @->>> __"Hello!" <> whenF showDetails (", details: "\#|foobar|\#"")__+>>> __"Hello!" <> whenF showDetails (", details: "+|foobar|+"")__ @ Note that it can only take a 'Builder' (because otherwise it would be-unusable with ('#|')-formatted strings which can resolve to any 'FromBuilder'). Thus, use 'fmt' if you need just one value:+unusable with ('+|')-formatted strings which can resolve to any 'FromBuilder'). Thus, use 'fmt' if you need just one value: @->>> __"Maybe here's a number: "\#|whenF cond (fmt n)|\#""__+>>> __"Maybe here's a number: "+|whenF cond (fmt n)|+""__ @ -} whenF :: Bool -> Builder -> Builder@@ -1309,7 +1309,7 @@ * mention that fmt doesn't do the neat thing that formatting does with (<>) (or maybe it does? there's a monoid instance for functions after all, though I might also have to write a IsString instance for (a -> Builder))-* write that if #| |# are hated or if it's inconvenient in some cases,+* write that if +| |+ are hated or if it's inconvenient in some cases, you can just use provided formatters and <> (add Fmt.DIY for that?) (e.g. "pub:" <> base16F foo) * write that it can be used in parallel with formatting? can it, actually?
tests/Main.hs view
@@ -67,32 +67,32 @@ test_operators :: Spec test_operators = do it "simple examples" $ do- ("a"#|n|#"b") ==%> "a25b"- ("a"#|n|#"b"#|s|#"") ==%> "a25b!"- (""#|n|##|s|#"") ==%> "25!"- (""#|negate n|##|s|#"") ==%> "-25!"- (""#|Just n|##|s|#"") ==%> "25!"+ ("a"+|n|+"b") ==%> "a25b"+ ("a"+|n|+"b"+|s|+"") ==%> "a25b!"+ (""+|n|++|s|+"") ==%> "25!"+ (""+|negate n|++|s|+"") ==%> "-25!"+ (""+|Just n|++|s|+"") ==%> "25!" describe "examples with Show/mixed" $ do it "copy of Buildable examples" $ do- ("a"#||n||#"b") ==%> "a25b"- ("a"#||n||##||n||#"b") ==%> "a2525b"+ ("a"+||n||+"b") ==%> "a25b"+ ("a"+||n||++||n||+"b") ==%> "a2525b" -- These are mixed, i.e. both Buildable and Show versions are used- ("a"#||n||#"b"#|s|#"") ==%> "a25b!"- (""#||n||##|s|#"") ==%> "25!"- (""#||negate n||##|s|#"") ==%> "-25!"+ ("a"+||n||+"b"+|s|+"") ==%> "a25b!"+ (""+||n||++|s|+"") ==%> "25!"+ (""+||negate n||++|s|+"") ==%> "-25!" it "examples that don't work with Buildable" $ do- (""#||Just n||#"") ==%> "Just 25"- (""#||(n,n)||#"") ==%> "(25,25)"+ (""+||Just n||+"") ==%> "Just 25"+ (""+||(n,n)||+"") ==%> "(25,25)" it "plays nice with other operators" $ do -- If precedence is bad these won't compile- (""#|n-1|##|n+1|#"") ==%> "2426"- (id $ ""#|n-1|##|n+1|#"") ==%> "2426"+ (""+|n-1|++|n+1|+"") ==%> "2426"+ (id $ ""+|n-1|++|n+1|+"") ==%> "2426" it "works with <>" $ do- ("number: "#|n|#"\n"<>- "string: "#|s|#"") ==%> "number: 25\nstring: !"+ ("number: "+|n|+"\n"<>+ "string: "+|s|+"") ==%> "number: 25\nstring: !" ---------------------------------------------------------------------------- -- Testing that different output types work@@ -101,13 +101,13 @@ test_outputTypes :: Spec test_outputTypes = describe "output as" $ do it "String" $- ("a"#|n|#"b" :: String) `shouldBe` "a25b"+ ("a"+|n|+"b" :: String) `shouldBe` "a25b" it "Text" $- ("a"#|n|#"b" :: Text) `shouldBe` "a25b"+ ("a"+|n|+"b" :: Text) `shouldBe` "a25b" it "Lazy Text" $- ("a"#|n|#"b" :: TL.Text) `shouldBe` "a25b"+ ("a"+|n|+"b" :: TL.Text) `shouldBe` "a25b" it "Builder" $- ("a"#|n|#"b" :: Builder) `shouldBe` "a25b"+ ("a"+|n|+"b" :: Builder) `shouldBe` "a25b" ---------------------------------------------------------------------------- -- Tests for various simple formatters@@ -126,8 +126,8 @@ it "formatting a block" $ do ("Some numbers:\n"<> indent 2 (- "odd: "#|n|#"\n"<>- "even: "#|n+1|#"")) ==#> "Some numbers:\n odd: 25\n even: 26\n"+ "odd: "+|n|+"\n"<>+ "even: "+|n+1|+"")) ==#> "Some numbers:\n odd: 25\n even: 26\n" test_baseConversion :: Spec test_baseConversion = describe "conversion to bases" $ do