fmt 0.0.0.3 → 0.0.0.4
raw patch · 5 files changed
+71/−63 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Fmt: padCenterF :: Buildable a => Int -> Char -> a -> Builder
+ Fmt: data Format :: *
+ Fmt: format :: (FromBuilder b, Params ps) => Format -> ps -> b
+ Fmt: formatLn :: (FromBuilder b, Params ps) => Format -> ps -> b
+ Fmt: padBothF :: Buildable a => Int -> Char -> a -> Builder
Files
- CHANGELOG.md +8/−0
- fmt.cabal +1/−1
- lib/Fmt.hs +40/−35
- lib/Fmt/Internal.hs +5/−10
- tests/Main.hs +17/−17
CHANGELOG.md view
@@ -1,3 +1,11 @@+# 0.0.0.4++* Added `format` from `text-format`, because in some cases it's nicer than brackets.++* Renamed `padCenterF` to `padBothF`.++* Modified `indent` and `indent'` to always add newlines.+ # 0.0.0.3 * Wrote documentation.
fmt.cabal view
@@ -1,5 +1,5 @@ name: fmt-version: 0.0.0.3+version: 0.0.0.4 synopsis: Nice formatting library description: Nice formatting library
lib/Fmt.hs view
@@ -1,7 +1,7 @@ {- Acknowledgements ~~~~~~~~~~~~~~~~~~~ -* 'prefixF', 'suffixF', 'padCenterF', 'groupInt' are taken from+* 'prefixF', 'suffixF', 'padBothF', 'groupInt' are taken from <https://hackage.haskell.org/package/formatting> Written by Github user @mwm <https://github.com/mwm>@@ -48,6 +48,11 @@ (>%%<<), (>>%%<), + -- * Old-style formatting+ format,+ formatLn,+ TF.Format,+ -- * Helper functions fmt, fmtLn,@@ -82,7 +87,7 @@ suffixF, padLeftF, padRightF,- padCenterF,+ padBothF, -- ** Hex hexF,@@ -116,11 +121,11 @@ import Data.Monoid import Lens.Micro -- Text-import qualified Data.Text as T import qualified Data.Text.Lazy as TL -- 'Buildable' and text-format import Data.Text.Buildable import qualified Data.Text.Format as TF+import qualified Data.Text.Format.Params as TF -- Text 'Builder' import Data.Text.Lazy.Builder hiding (fromString) -- 'Foldable' and 'IsList' for list/map formatters@@ -316,9 +321,21 @@ infixr 1 >%%<< ------------------------------------------------------------------------------- Main functions+-- Old-style formatting ---------------------------------------------------------------------------- +format :: (FromBuilder b, TF.Params ps) => TF.Format -> ps -> b+format f ps = fromBuilder (TF.build f ps)+{-# INLINE format #-}++formatLn :: (FromBuilder b, TF.Params ps) => TF.Format -> ps -> b+formatLn f ps = fromBuilder (TF.build f ps <> "\n")+{-# INLINE formatLn #-}++----------------------------------------------------------------------------+-- Helper functions+----------------------------------------------------------------------------+ {- | 'fmt' converts things to 'String', 'Text' or 'Builder'. Most of the time you won't need it, as strings produced with ('%<') and@@ -368,6 +385,8 @@ >>> listF ["hello", "world"] "[hello, world]"++For multiline output, use 'jsonListF'. -} listF :: (Foldable f, Buildable a) => f a -> Builder listF = listF' build@@ -509,10 +528,12 @@ #endif {- | A simple JSON-like map formatter; works for Map, HashMap, etc, as well as-ordinary lists of pairs. Doesn't handle multiline elements (for that you need 'blockMapF' or 'jsonMapF').+ordinary lists of pairs. >>> mapF [("a", 1), ("b", 4)] "{a: 1, b: 4}"++For multiline output, use 'jsonMapF'. -} mapF :: #if __GLASGOW_HASKELL__ >= 708@@ -809,22 +830,22 @@ padRightF = TF.right {- |-@padCenterF n c@ pads the string with character @c@ from both sides until+@padBothF n c@ pads the string with character @c@ from both sides until it becomes @n@ characters wide (and does nothing if the string is already that long, or longer): ->>> padCenterF 5 '=' "foo"+>>> padBothF 5 '=' "foo" "=foo="->>> padCenterF 5 '=' "foobar"+>>> padBothF 5 '=' "foobar" "foobar" When padding can't be distributed equally, the left side is preferred: ->>> padCenter 8 '=' "foo"+>>> padBoth 8 '=' "foo" "===foo==" -}-padCenterF :: Buildable a => Int -> Char -> a -> Builder-padCenterF i c =+padBothF :: Buildable a => Int -> Char -> a -> Builder+padBothF i c = fromLazyText . TL.center (fromIntegral i) c . toLazyText . build {- |@@ -983,23 +1004,15 @@ - 1 - 2 - 3++The output will always end with a newline, even when the input doesn't. -} indent :: Int -> Builder -> Builder-indent n a = go (toLazyText a)+indent n a = case TL.lines (toLazyText a) of+ [] -> fromLazyText (spaces <> "\n")+ xs -> fromLazyText $ TL.unlines (map (spaces <>) xs) where- spaces = fromText (T.replicate n (T.singleton ' '))- -- We don't use 'lines' because it doesn't distinguish between trailing- -- newline being present/absent. We want the following behavior:- -- >>> indent 2 "hi"- -- " hi"- -- >>> indent 2 "hi\n"- -- " hi\n"- go t | TL.null t = mempty- go t = let (l, t') = TL.break ((==) '\n') t- in spaces <> if TL.null t'- then fromLazyText l- else fromLazyText l <> singleton '\n' <>- go (TL.tail t')+ spaces = TL.replicate (fromIntegral n) (TL.singleton ' ') ---------------------------------------------------------------------------- -- TODOs@@ -1023,16 +1036,11 @@ (and maybe not in the middle as well) * the problem is that the user might want to combine them so I guess we can't make a separate combinator for each-* there don't seem to be any cases when 'listF' is better than 'jsonListF',- so we'd want to leave only one of those, but there are cases when 'mapF' is- better than 'jsonMapF' (i.e. when you want everything to be on one- line). What to do? Maybe rename 'jsonMapF' to 'mapF' and 'mapF' to ???- (can't think of a name)? -} {- docs -* add an examples section in the beginning+* write explicitly that 'build' can be used and is useful sometimes * provide a formatting→fmt transition table * 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,@@ -1045,13 +1053,10 @@ * clarify philosophy (“take a free spot in design space; write the best possible library around it, not just a proof of concept”) * clarify what exactly is hard about writing `formatting` formatters-* write that [(a,b)] works too and could be used -} {- others -* rename 'padCenterF'-* change indentation to always add newlines * something to format a record nicely (with generics, probably) * something like https://hackage.haskell.org/package/groom * something for wrapping lists (not indenting, just hard-wrapping)@@ -1060,7 +1065,7 @@ * should it be called 'listBlock' or 'blockList'? * add NL or _NL for newline? or (<\>) or (<>\)? and also (>%\)? * have to decide on whether it would be >%< or >%%< or maybe >|<-* actually, what about |< and >|?+* actually, what about |< and >|? also <% and %> are good * what effect does it have on compilation time? what effect do other formatting libraries have on compilation time? * use 4 spaces instead of 2?
lib/Fmt/Internal.hs view
@@ -179,14 +179,9 @@ -- assumes that the prefix doesn't contain newlines indent' :: Int -> T.Text -> Builder -> Builder-indent' n pref a = go True (toLazyText a)+indent' n pref a = case TL.lines (toLazyText a) of+ [] -> fromText pref <> "\n"+ (x:xs) -> fromLazyText $+ TL.unlines $ (TL.fromStrict pref <> x) : map (spaces <>) xs where- spaces = fromText (T.replicate n (T.singleton ' '))- go isFirst t- | TL.null t = if isFirst then fromText pref else ""- | otherwise = let (l, t') = TL.break ((==) '\n') t- in (if isFirst then fromText pref else spaces) <>- if TL.null t'- then fromLazyText l- else fromLazyText l <> singleton '\n' <>- go False (TL.tail t')+ spaces = TL.replicate (fromIntegral n) (TL.singleton ' ')
tests/Main.hs view
@@ -75,18 +75,18 @@ describe "formatters" $ do describe "'indent'" $ do it "simple examples" $ do- indent 0 "hi" ==#> "hi"+ indent 0 "hi" ==#> "hi\n" indent 0 "\nhi\n\n" ==#> "\nhi\n\n"- indent 2 "hi" ==#> " hi"+ indent 2 "hi" ==#> " hi\n" indent 2 "hi\n" ==#> " hi\n"- indent 2 "" ==#> ""- indent 2 "hi\nbye" ==#> " hi\n bye"+ indent 2 "" ==#> " \n"+ indent 2 "hi\nbye" ==#> " hi\n bye\n" indent 2 "hi\nbye\n" ==#> " hi\n bye\n" it "formatting a block" $ do ("Some numbers:\n"<> indent 2 ( "odd: "%<n>%"\n"<>- "even: "%<n+1>%"")) ==#> "Some numbers:\n odd: 25\n even: 26"+ "even: "%<n+1>%"")) ==#> "Some numbers:\n odd: 25\n even: 26\n" describe "'listF'" $ do it "simple examples" $ do@@ -474,18 +474,18 @@ padRightF 6 '!' ("hello" :: Text) ==#> "hello!" padRightF 7 '!' ("hello" :: Text) ==#> "hello!!" padRightF 7 '!' ("" :: Text) ==#> "!!!!!!!"- it "padCenterF" $ do- padCenterF (-1) '!' ("hello" :: Text) ==#> "hello"- padCenterF 0 '!' ("hello" :: Text) ==#> "hello"- padCenterF 1 '!' ("hello" :: Text) ==#> "hello"- padCenterF 5 '!' ("hello" :: Text) ==#> "hello"- padCenterF 6 '!' ("hello" :: Text) ==#> "!hello"- padCenterF 7 '!' ("hello" :: Text) ==#> "!hello!"- padCenterF 7 '!' ("hell" :: Text) ==#> "!!hell!"- padCenterF 7 '!' ("hel" :: Text) ==#> "!!hel!!"- padCenterF 8 '!' ("hell" :: Text) ==#> "!!hell!!"- padCenterF 8 '!' ("hel" :: Text) ==#> "!!!hel!!"- padCenterF 8 '!' ("" :: Text) ==#> "!!!!!!!!"+ it "padBothF" $ do+ padBothF (-1) '!' ("hello" :: Text) ==#> "hello"+ padBothF 0 '!' ("hello" :: Text) ==#> "hello"+ padBothF 1 '!' ("hello" :: Text) ==#> "hello"+ padBothF 5 '!' ("hello" :: Text) ==#> "hello"+ padBothF 6 '!' ("hello" :: Text) ==#> "!hello"+ padBothF 7 '!' ("hello" :: Text) ==#> "!hello!"+ padBothF 7 '!' ("hell" :: Text) ==#> "!!hell!"+ padBothF 7 '!' ("hel" :: Text) ==#> "!!hel!!"+ padBothF 8 '!' ("hell" :: Text) ==#> "!!hell!!"+ padBothF 8 '!' ("hel" :: Text) ==#> "!!!hel!!"+ padBothF 8 '!' ("" :: Text) ==#> "!!!!!!!!" describe "integer" $ do it "octF" $ do