diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,36 @@
+1.0.14
+
+* [Improve whitespace handling](https://github.com/Gabriel439/nix-diff/pull/40)
+    * `--word-oriented` now treats all whitespace characters as word
+      boundaries instead of just spaces
+
+      This matches the behavior of `Prelude.words`
+
+    * `--word-oriented` no longer highlights the intervening spaces between
+      words
+
+      This is for consistency with `--line-oriented`, which doesn't
+      highlight the intervening spaces between lines.  Also, you could argue
+      that if the user specifies `--word-oriented` then they want all new
+      tokens to be highlighted on a word-by-word basis.
+
+    * `--line-oriented` now no longer introduces a trailing newline at the
+      end of a newline-free segment of text
+
+    * More generally, both `--word-oriented` and `--newline-oriented`
+      exactly preserve the original whitespace that was used for word or
+      line boundaries.
+
+1.0.13
+
+* [Add new `--word-oriented` mode, which is now the new default mode](https://github.com/Gabriel439/nix-diff/pull/38)
+    * This now diffs on word boundaries instead of line-boundaries
+
+1.0.12
+
+* [Use "patience" diff algorithm](https://github.com/Gabriel439/nix-diff/pull/33)
+    * This improves the quality of the diff
+
+1.0.11
+
+* [Add support for diffing input sources](https://github.com/Gabriel439/nix-diff/pull/30)
diff --git a/nix-diff.cabal b/nix-diff.cabal
--- a/nix-diff.cabal
+++ b/nix-diff.cabal
@@ -1,5 +1,5 @@
 name:                nix-diff
-version:             1.0.13
+version:             1.0.14
 synopsis:            Explain why two Nix derivations differ
 description:         This package provides a @nix-diff@ executable which
                      explains why two Nix derivations (i.e. @*.drv@ files)
@@ -15,6 +15,7 @@
 tested-with:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.8.3
 cabal-version:       >= 1.10
 extra-source-files:  README.md
+                     CHANGELOG.md
 
 executable nix-diff
   main-is:             Main.hs
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -28,7 +28,9 @@
 import qualified Control.Monad.Reader
 import qualified Control.Monad.State
 import qualified Data.Attoparsec.Text
+import qualified Data.Char            as Char
 import qualified Data.Map
+import qualified Data.List            as List
 import qualified Data.Set
 import qualified Data.Text
 import qualified Data.Text.IO
@@ -115,7 +117,7 @@
 parserInfo :: ParserInfo Options
 parserInfo =
     Options.Applicative.info
-        parseOptions
+        (Options.Applicative.helper <*> parseOptions)
         (   Options.Applicative.fullDesc
         <>  Options.Applicative.header "Explain why two derivations differ"
         )
@@ -237,35 +239,38 @@
 
 -- | Color text background red
 redBackground  :: Orientation -> TTY -> Text -> Text
-redBackground Character IsTTY  text = "\ESC[41m" <> text <> "\ESC[0m"
-redBackground Word      IsTTY  text = "\ESC[41m" <> text <> " \ESC[0m"
-redBackground Line      IsTTY  text = "\ESC[41m" <> text <> "\ESC[0m\n"
-redBackground Character NotTTY text = "←" <> text <> "←"
-redBackground Word      NotTTY text = "←" <> text <> " ←"
-redBackground Line      NotTTY text = "- " <> text <> "\n"
+redBackground Line IsTTY text = "\ESC[41m" <> prefix <> "\ESC[0m" <> suffix
+  where
+    (prefix, suffix) = Data.Text.break lineBoundary text
+redBackground Word IsTTY text = "\ESC[41m" <> prefix <> "\ESC[0m" <> suffix
+  where
+    (prefix, suffix) = Data.Text.break wordBoundary text
+redBackground Character IsTTY text = "\ESC[41m" <> text <> "\ESC[0m"
+redBackground Line NotTTY text = "- " <> text
+redBackground _    NotTTY text = "←" <> text <> "←"
 
 -- | Color text green
 green :: TTY -> Text -> Text
-green  IsTTY text = "\ESC[1;32m" <> text <> "\ESC[0m"
+green IsTTY  text = "\ESC[1;32m" <> text <> "\ESC[0m"
 green NotTTY text = text
 
 -- | Color text background green
 greenBackground :: Orientation -> TTY -> Text -> Text
+greenBackground Line IsTTY text = "\ESC[42m" <> prefix <> "\ESC[0m" <> suffix
+  where
+    (prefix, suffix) = Data.Text.break lineBoundary text
+greenBackground Word IsTTY text = "\ESC[42m" <> prefix <> "\ESC[0m" <> suffix
+  where
+    (prefix, suffix) = Data.Text.break wordBoundary text
 greenBackground Character IsTTY  text = "\ESC[42m" <> text <> "\ESC[0m"
-greenBackground Word      IsTTY  text = "\ESC[42m" <> text <> " \ESC[0m"
-greenBackground Line      IsTTY  text = "\ESC[42m" <> text <> "\ESC[0m\n"
-greenBackground Character NotTTY text = "→" <> text <> "→"
-greenBackground Word      NotTTY text = "→" <> text <> " →"
-greenBackground Line      NotTTY text = "+ " <> text <> "\n"
+greenBackground Line NotTTY text = "+ " <> text
+greenBackground _    NotTTY text = "→" <> text <> "→"
 
 -- | Color text grey
 grey :: Orientation -> TTY -> Text -> Text
-grey Character IsTTY  text = "\ESC[1;2m" <> text <> "\ESC[0m"
-grey Word      IsTTY  text = "\ESC[1;2m" <> text <> " \ESC[0m"
-grey Line      IsTTY  text = "\ESC[1;2m" <> text <> "\ESC[0m\n"
-grey Character NotTTY text = text
-grey Word      NotTTY text = text <> " "
-grey Line      NotTTY text = "  " <> text <> "\n"
+grey _    IsTTY  text = "\ESC[1;2m" <> text <> "\ESC[0m"
+grey Line NotTTY text = "  " <> text
+grey _    NotTTY text = text
 
 -- | Format the left half of a diff
 minus :: TTY -> Text -> Text
@@ -381,6 +386,40 @@
 mapDiff f (Patience.New    r) = Patience.New (f r)
 mapDiff f (Patience.Both l r) = Patience.Both (f l) (f r)
 
+{-| Split `Text` into spans of `Text` that alternatively fail and satisfy the
+    given predicate
+
+    The first span (if present) does not satisfy the predicate (even if the
+    span is empty)
+
+    >>> decomposeOn (== 'b') "aabbaa"
+    ["aa","bb","aa"]
+    >>> decomposeOn (== 'b') "bbaa"
+    ["","bb","aa"]
+    >>> decomposeOn (== 'b') ""
+    []
+-}
+decomposeOn :: (Char -> Bool) -> Text -> [Text]
+decomposeOn predicate = unsatisfy
+  where
+    unsatisfy text
+        | Data.Text.null text = []
+        | otherwise           = prefix : satisfy suffix
+      where
+        (prefix, suffix) = Data.Text.break predicate text
+
+    satisfy text
+        | Data.Text.null text = []
+        | otherwise           = prefix : unsatisfy suffix
+      where
+        (prefix, suffix) = Data.Text.span predicate text
+
+lineBoundary :: Char -> Bool
+lineBoundary = ('\n' ==)
+
+wordBoundary :: Char -> Bool
+wordBoundary = Char.isSpace
+
 -- | Diff two `Text` values
 diffText
     :: Text
@@ -396,11 +435,19 @@
     let leftString  = Data.Text.unpack left
     let rightString = Data.Text.unpack right
 
-    let leftWords  = Data.Text.splitOn " " left
-    let rightWords = Data.Text.splitOn " " right
+    let decomposeWords = decomposeOn wordBoundary
 
-    let leftLines  = Data.Text.lines left
-    let rightLines = Data.Text.lines right
+    let decomposeLines text = loop (decomposeOn lineBoundary text)
+          where
+            -- Groups each newline character with the preceding line
+            loop (x : y : zs) = (x <> y) : loop zs
+            loop          zs  = zs
+
+    let leftWords  = decomposeWords left
+    let rightWords = decomposeWords right
+
+    let leftLines  = decomposeLines left
+    let rightLines = decomposeLines right
 
     let chunks =
             case orientation of
