diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,19 @@
+# 0.5.0.0
+
+* From this version on, `blockListF` never puts blank lines between items.
+  If you want blank lines between items, I'm afraid that you'll have to add
+  them manually (by e.g. adding a blank line to each item).
+
+* Now `blockListF'` can be used to create lists with custom bullets.
+
+* Added `unwordsF` and `unlinesF`.
+
+* Added the `F` suffix to `indent` and `indent'`.
+
 # 0.4.0.0
 
-* Renamed `#|` and `|#` to `+|` and `|+` because HLint can't handle `#|` and everyone uses HLint apparently.
+* Renamed `#|` and `|#` to `+|` and `|+` because HLint can't handle `#|` and
+  everyone uses HLint apparently.
 
 # 0.3.0.0
 
@@ -14,7 +27,8 @@
 
 * Added `genericF` for formatting arbitrary data.
 
-* Changed `%<` and `>%` to `#|` and `|#` because they turn out to be easier to type.
+* Changed `%<` and `>%` to `#|` and `|#` because they turn out to be easier
+  to type.
 
 * Added a migration guide from `formatting`.
 
@@ -24,7 +38,8 @@
 
 # 0.0.0.4
 
-* Added `format` from `text-format`, because in some cases it's nicer than brackets.
+* Added `format` from `text-format`, because in some cases it's nicer than
+  brackets.
 
 * Renamed `padCenterF` to `padBothF`.
 
@@ -51,23 +66,28 @@
 
 * Added `fmt` and `fmtLn`.
 
-* Made all operators associate to the right (`Builder` documentation says it's faster than the opposite).
+* Made all operators associate to the right (`Builder` documentation says
+  it's faster than the opposite).
 
 * Reexported `Buildable` and `Builder`.
 
 # 0.0.0.2
 
-* Added `>%%<` so that it'd be possible to write `%<a>%%<b>%` instead of weird `%<a%<b>%`.
+* Added `>%%<` so that it'd be possible to write `%<a>%%<b>%` instead of
+  weird `%<a%<b>%`.
 
-* Added `%<< ... >>%`, which work work `Show` instead of `Buildable`. If you don't care about speed and just want to output something, use them.
+* Added `%<< ... >>%`, which work work `Show` instead of `Buildable`. If you
+  don't care about speed and just want to output something, use them.
 
-* Added an `IO ()` instance in `Fmt.IO`. If you import that module, raw formatted strings would print themselves.
+* Added an `IO ()` instance in `Fmt.IO`. If you import that module, raw
+  formatted strings would print themselves.
 
 * Added tests.
 
 * Changed fixities of operators so that `%<n+1>%` would work.
 
-* Changed license to BSD3 since all our dependencies are BSD3 and we can't use MIT.
+* Changed license to BSD3 since all our dependencies are BSD3 and we can't
+  use MIT.
 
 # 0.0.0.1
 
diff --git a/fmt.cabal b/fmt.cabal
--- a/fmt.cabal
+++ b/fmt.cabal
@@ -1,5 +1,5 @@
 name:                fmt
-version:             0.4.0.0
+version:             0.5.0.0
 synopsis:            A new formatting library
 description:
   A new formatting library that tries to be simple to understand while still
diff --git a/lib/Fmt.hs b/lib/Fmt.hs
--- a/lib/Fmt.hs
+++ b/lib/Fmt.hs
@@ -82,12 +82,16 @@
   Buildable(..),
 
   -- * Formatters
-  indent, indent',
-  nameF,
 
   -- ** Time
   module Fmt.Time,
 
+  -- ** Text
+  indentF, indentF',
+  nameF,
+  unwordsF,
+  unlinesF,
+
   -- ** Lists
   listF, listF',
   blockListF, blockListF',
@@ -157,6 +161,7 @@
 import qualified Data.IntSet as IntSet
 import Data.Sequence (Seq)
 -- Text
+import qualified Data.Text as T
 import qualified Data.Text.Lazy as TL
 -- 'Buildable' and text-format
 import Data.Text.Buildable
@@ -186,7 +191,8 @@
 
 {- $overloadedstrings
 
-You need @OverloadedStrings@ enabled to use this library. There are three ways to do it:
+You need @OverloadedStrings@ enabled to use this library. There are three
+ways to do it:
 
   * __In GHCi:__ do @:set -XOverloadedStrings@.
 
@@ -248,8 +254,8 @@
 
 The resulting formatted string is polymorphic and can be used as 'String',
 'Text', 'Builder' or even 'IO' (i.e. the string will be printed to the
-screen). However, when printing it is recommended to use 'fmt' or 'fmtLn' for
-clarity.
+screen). However, when printing it is recommended to use 'fmt' or 'fmtLn'
+for clarity.
 
 @fmt@ provides lots of formatters (which are simply functions that produce
 'Builder'):
@@ -291,7 +297,6 @@
 * @plural@ and @asInt@ (but instead of @asInt@ you can use 'fromEnum')
 * @prefixBin@, @prefixOrd@, @prefixHex@, and @bytes@
 * formatters that use @Scientific@ (@sci@ and @scifmt@)
-* formatters that deal with time (anything from @Formatting.Time@)
 
 They will be added later. (On the other hand, @fmt@ provides some useful
 formatters not available in @formatting@, such as 'listF', 'mapF', 'tupleF'
@@ -323,8 +328,8 @@
 Meet Alice!
 
 Otherwise the type of the formatted string would be resolved to @IO ()@ and
-printed without a newline, which is not very convenient when you're in
-GHCi. On the other hand, it's useful for quick-and-dirty scripts:
+printed without a newline, which is not very convenient when you're in GHCi.
+On the other hand, it's useful for quick-and-dirty scripts:
 
 @
 main = do
@@ -499,9 +504,27 @@
 {-# INLINE fmtLn #-}
 
 ----------------------------------------------------------------------------
--- Formatters
+-- Text formatters
 ----------------------------------------------------------------------------
 
+{- |
+Indent a block of text.
+
+>>> fmt $ "This is a list:\n" <> indentF 4 (blockListF [1,2,3])
+This is a list:
+    - 1
+    - 2
+    - 3
+
+The output will always end with a newline, even when the input doesn't.
+-}
+indentF :: Int -> Builder -> Builder
+indentF n a = case TL.lines (toLazyText a) of
+    [] -> fromLazyText (spaces <> "\n")
+    xs -> fromLazyText $ TL.unlines (map (spaces <>) xs)
+  where
+    spaces = TL.replicate (fromIntegral n) (TL.singleton ' ')
+
 {- | Attach a name to anything:
 
 >>> fmt $ nameF "clients" $ blockListF ["Alice", "Bob", "Zalgo"]
@@ -517,6 +540,35 @@
     ls  -> k <> ":\n" <>
            mconcat ["  " <> fromLazyText s <> "\n" | s <- ls]
 
+{- | Put words between elements.
+
+>>> fmt $ unwordsF ["hello", "world"]
+hello world
+
+Of course, it works on anything 'Buildable':
+
+>>> fmt $ unwordsF [1, 2]
+1 2
+-}
+unwordsF :: (Foldable f, Buildable a) => f a -> Builder
+unwordsF = mconcat . intersperse " " . map build . toList
+
+{-# SPECIALIZE unwordsF :: Buildable a => [a] -> Builder #-}
+
+{- | Arrange elements on separate lines.
+
+>>> fmt $ unlines ["hello", "world"]
+hello
+world
+-}
+unlinesF :: (Foldable f, Buildable a) => f a -> Builder
+unlinesF = mconcat . map (nl . build) . toList
+  where
+    nl x | "\n" `TL.isSuffixOf` toLazyText x = x
+         | otherwise = x <> "\n"
+
+{-# SPECIALIZE unlinesF :: Buildable a => [a] -> Builder #-}
+
 ----------------------------------------------------------------------------
 -- List formatters
 ----------------------------------------------------------------------------
@@ -554,8 +606,8 @@
 
 The documentation for 'Builder' says that it's preferrable to associate
 'Builder' appends to the right (i.e. @a <> (b <> c)@). The maximum possible
-association-to-the-right is achieved when we avoid appending builders
-until the last second (i.e. in the latter scenario):
+association-to-the-right is achieved when we avoid appending builders until
+the last second (i.e. in the latter scenario):
 
     -- (a1 <> x) <> (a2 <> x) <> ...
     mconcat [a <> x | a <- as]
@@ -573,41 +625,41 @@
 - 2
 - 3
 
-It automatically handles multiline list elements:
+Multi-line elements are indented correctly:
 
 @
 >>> __fmt $ blockListF ["hello\\nworld", "foo\\nbar\\nquix"]__
 - hello
   world
-
 - foo
   bar
   quix
 @
 -}
 blockListF :: forall f a. (Foldable f, Buildable a) => f a -> Builder
-blockListF = blockListF' build
+blockListF = blockListF' "-" build
 {-# INLINE blockListF #-}
 
 {- | A version of 'blockListF' that lets you supply your own building function
-for list elements.
+for list elements (instead of 'build') and choose the bullet character
+(instead of @"-"@).
 -}
-blockListF' :: forall f a. (Foldable f) => (a -> Builder) -> f a -> Builder
-blockListF' fbuild xs
-  | null items      = "[]\n"
-  | True `elem` mls = mconcat (intersperse "\n" items)
-  | otherwise       = mconcat items
+blockListF'
+  :: forall f a. Foldable f
+  => T.Text                     -- ^ Bullet
+  -> (a -> Builder)             -- ^ Builder for elements
+  -> f a                        -- ^ Structure with elements
+  -> Builder
+blockListF' bullet fbuild xs = if null items then "[]\n" else mconcat items
   where
-    (mls, items) = unzip $ map buildItem (toList xs)
-    -- Returns 'True' if the item is multiline
-    buildItem :: a -> (Bool, Builder)
+    items = map buildItem (toList xs)
+    spaces = mconcat $ replicate (T.length bullet + 1) (singleton ' ')
     buildItem x = case TL.lines (toLazyText (fbuild x)) of
-      []     -> (False, "-\n")
-      (l:ls) -> (not (null ls),
-                 "- " <> fromLazyText l <> "\n" <>
-                     mconcat ["  " <> fromLazyText s <> "\n" | s <- ls])
+      []     -> bullet |+ "\n"
+      (l:ls) -> bullet |+ " " +| l |+ "\n" <>
+                mconcat [spaces <> fromLazyText s <> "\n" | s <- ls]
 
-{-# SPECIALIZE blockListF' :: (a -> Builder) -> [a] -> Builder #-}
+{-# SPECIALIZE blockListF' :: T.Text -> (a -> Builder) -> [a] -> Builder #-}
 
 {- | A JSON-style formatter for lists.
 
@@ -628,8 +680,6 @@
   bar
   quix
 ]
-
-(Note that, unlike 'blockListF', it doesn't add blank lines in such cases.)
 -}
 jsonListF :: forall f a. (Foldable f, Buildable a) => f a -> Builder
 jsonListF = jsonListF' build
@@ -1085,28 +1135,6 @@
 {-# INLINE unlessF #-}
 
 ----------------------------------------------------------------------------
--- Utilities
-----------------------------------------------------------------------------
-
-{- |
-Indent already formatted text.
-
->>> fmt $ "This is a list:\n" <> indent 4 (blockListF [1,2,3])
-This is a list:
-    - 1
-    - 2
-    - 3
-
-The output will always end with a newline, even when the input doesn't.
--}
-indent :: Int -> Builder -> Builder
-indent n a = case TL.lines (toLazyText a) of
-    [] -> fromLazyText (spaces <> "\n")
-    xs -> fromLazyText $ TL.unlines (map (spaces <>) xs)
-  where
-    spaces = TL.replicate (fromIntegral n) (TL.singleton ' ')
-
-----------------------------------------------------------------------------
 -- Generic formatting
 ----------------------------------------------------------------------------
 
@@ -1294,14 +1322,6 @@
 ----------------------------------------------------------------------------
 -- TODOs
 ----------------------------------------------------------------------------
-
-{- list/map
-~~~~~~~~~~~~~~~~~~~~
-* maybe add something like blockMapF_ and blockListF_ that would add
-  a blank line automatically? or `---` and `:::` or something?
-* should also add something to _not_ add a blank line between list
-  entries (e.g. when they are 'name'd and can be clearly differentiated)
--}
 
 {- docs
 ~~~~~~~~~~~~~~~~~~~~
diff --git a/lib/Fmt/Internal.hs b/lib/Fmt/Internal.hs
--- a/lib/Fmt/Internal.hs
+++ b/lib/Fmt/Internal.hs
@@ -16,8 +16,8 @@
 #  define _OVERLAPS_ {-# OVERLAPS #-}
 #endif
 
-{- | A module providing access to internals (in case you really need them). Can
-change at any time, though probably won't.
+{- | A module providing access to internals (in case you really need them).
+Can change at any time, though probably won't.
 
 It also provides some functions that are used in 'Fmt.Time' (so that
 'Fmt.Time' wouldn't need to import 'Fmt').
@@ -43,7 +43,7 @@
   atBase,
   showSigned',
   intToDigit',
-  indent',
+  indentF',
 
   -- * Functions used in 'Fmt.Time'
   fixedF,
@@ -257,8 +257,8 @@
 
 The output will always end with a newline, even when the input doesn't.
 -}
-indent' :: Int -> T.Text -> Builder -> Builder
-indent' n pref a = case TL.lines (toLazyText a) of
+indentF' :: Int -> T.Text -> Builder -> Builder
+indentF' n pref a = case TL.lines (toLazyText a) of
   []     -> fromText pref <> "\n"
   (x:xs) -> fromLazyText $
             TL.unlines $ (TL.fromStrict pref <> x) : map (spaces <>) xs
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -114,18 +114,18 @@
 ----------------------------------------------------------------------------
 
 test_indent :: Spec
-test_indent = describe "'indent'" $ do
+test_indent = describe "'indentF'" $ do
   it "simple examples" $ do
-    indent 0 "hi" ==#> "hi\n"
-    indent 0 "\nhi\n\n" ==#> "\nhi\n\n"
-    indent 2 "hi" ==#> "  hi\n"
-    indent 2 "hi\n" ==#> "  hi\n"
-    indent 2 "" ==#> "  \n"
-    indent 2 "hi\nbye" ==#> "  hi\n  bye\n"
-    indent 2 "hi\nbye\n" ==#> "  hi\n  bye\n"
+    indentF 0 "hi" ==#> "hi\n"
+    indentF 0 "\nhi\n\n" ==#> "\nhi\n\n"
+    indentF 2 "hi" ==#> "  hi\n"
+    indentF 2 "hi\n" ==#> "  hi\n"
+    indentF 2 "" ==#> "  \n"
+    indentF 2 "hi\nbye" ==#> "  hi\n  bye\n"
+    indentF 2 "hi\nbye\n" ==#> "  hi\n  bye\n"
   it "formatting a block" $ do
     ("Some numbers:\n"<>
-     indent 2 (
+     indentF 2 (
        "odd: "+|n|+"\n"<>
        "even: "+|n+1|+"")) ==#> "Some numbers:\n  odd: 25\n  even: 26\n"
 
@@ -308,11 +308,9 @@
         blockListF (["a\n x"," b\nxx\ny y ","c\n\n"] :: [Text]) ==#> [text|
           - a
              x
-
           -  b
             xx
             y y_
-
           - c
           __
           |]
@@ -321,22 +319,18 @@
         blockListF (["a\nx","b"] :: [Text]) ==#> [text|
           - a
             x
-
           - b
           |]
         blockListF (["a\nx","b\n"] :: [Text]) ==#> [text|
           - a
             x
-
           - b
           |]
         blockListF (["a"," b\nxx\ny y ","c\n\n"] :: [Text]) ==#> [text|
           - a
-
           -  b
             xx
             y y_
-
           - c
           __
           |]
