diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@
 
     $ cabal install hindent
 
+You might need to `cabal install happy` if haskell-src-exts complains.
+
 ## Usage
 
     $ hindent
@@ -18,13 +20,18 @@
 ## Emacs
 
 In
-[elisp/hindent.el](https://github.com/chrisdone/hindent/blob/master/elisp/hindent.el),
-there is the function `hindent/reformat-decl` which you can run with
-`M-x hindent/reformat-decl`. Or alternatively define a keybinding,
-e.g.:
+[elisp/hindent.el](https://github.com/chrisdone/hindent/blob/master/elisp/hindent.el)
+there is `hindent-mode`, which provides keybindings to reindent parts of the
+buffer:
 
-``` lisp
-(define-key haskell-mode-map (kbd "C-c i") 'hindent/reformat-decl)
+- `M-q` reformats the current declaration.  When inside a comment, it fills the
+  current paragraph instead, like the standard `M-q`.
+- `C-M-\` reformats the current region.
+
+To enable it, add the following to your init file:
+
+```lisp
+(add-hook 'haskell-mode-hook #'hindent-mode)
 ```
 
 By default it uses the style called `fundamental`, if you want to use
diff --git a/elisp/hindent.el b/elisp/hindent.el
--- a/elisp/hindent.el
+++ b/elisp/hindent.el
@@ -27,7 +27,8 @@
   "fundamental"
   "The style to use for formatting."
   :group 'haskell
-  :type 'string)
+  :type 'string
+  :safe #'stringp)
 
 ;;;###autoload
 (defun hindent/reformat-decl ()
@@ -82,6 +83,19 @@
                           (message "Formatted."))
                       (message "Already formatted.")))))))))))))
 
+(defun hindent-reformat-decl-or-fill (justify)
+  "Re-format current declaration, or fill paragraph.
+
+Fill paragraph if in a comment, otherwise reformat the current
+declaration."
+  (interactive (progn
+                 ;; Copied from `fill-paragraph'
+                 (barf-if-buffer-read-only)
+                 (list (if current-prefix-arg 'full))))
+  (if (hindent-in-comment)
+      (fill-paragraph justify t)
+    (hindent/reformat-decl)))
+
 (defun hindent-decl-points (&optional use-line-comments)
   "Get the start and end position of the current
 declaration. This assumes that declarations start at column zero
@@ -178,6 +192,26 @@
     (save-restriction
       (mark-whole-buffer)
       (hindent-reformat-region))))
+
+(defvar hindent-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [remap indent-region] #'hindent-reformat-region)
+    (define-key map [remap fill-paragraph] #'hindent-reformat-decl-or-fill)
+    map)
+  "Keymap for `hindent-mode'.")
+
+;;;###autoload
+(define-minor-mode hindent-mode
+  "Indent code with the hindent program.
+
+Provide the following keybindings:
+
+\\{hindent-mode-map}"
+  :init-value nil
+  :keymap hindent-mode-map
+  :lighter " HI"
+  :group 'haskell
+  :require 'hindent)
 
 (provide 'hindent)
 
diff --git a/hindent.cabal b/hindent.cabal
--- a/hindent.cabal
+++ b/hindent.cabal
@@ -1,5 +1,5 @@
 name:                hindent
-version:             4.1.1
+version:             4.2.0
 synopsis:            Extensible Haskell pretty printer
 description:         Extensible Haskell pretty printer. Both a library and an executable.
                      .
@@ -40,6 +40,7 @@
   build-depends:     base >= 4 && < 5
                    , hindent
                    , text
+                   , descriptive >= 0.0.2 && < 0.1
 
 executable hindent-generate-tests
   hs-source-dirs:    src/main
diff --git a/src/main/Main.hs b/src/main/Main.hs
--- a/src/main/Main.hs
+++ b/src/main/Main.hs
@@ -1,4 +1,6 @@
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ViewPatterns #-}
+
 -- | Main entry point to hindent.
 --
 -- hindent
@@ -7,11 +9,14 @@
 
 import           HIndent
 
-import           Data.List
+import           Control.Applicative
+import           Data.Text (Text)
 import qualified Data.Text as T
 import qualified Data.Text.Lazy.Builder as T
 import qualified Data.Text.Lazy.IO as T
 import           Data.Version (showVersion)
+import           Descriptive
+import           Descriptive.Options
 import           Paths_hindent (version)
 import           System.Environment
 
@@ -19,16 +24,24 @@
 main :: IO ()
 main =
   do args <- getArgs
-     case args of
-       ["--style",findStyle -> Just style] ->
-         T.interact
-           (either error T.toLazyText .
-            reformat style)
-       ["--version"] -> putStrLn $ "hindent " ++ showVersion version
-       _ ->
-         error ("arguments: --style [" ++
-                intercalate "|"
-                            (map (T.unpack . styleName) styles) ++
-                "]")
-  where findStyle name =
-          find ((== T.pack name) . styleName) styles
+     case consume options (map T.pack args) of
+       Left{} ->
+         error (T.unpack (textDescription (describe options [])))
+       Right result ->
+         case result of
+           Left{} -> putStrLn ("hindent " ++ showVersion version)
+           Right style -> T.interact
+                            (either error T.toLazyText .
+                             reformat style)
+
+-- | Program options.
+options :: Consumer [Text] Option (Either Text (Style))
+options =
+  fmap Left (constant "--version") <|>
+  (fmap Right
+        (constant "--style" *>
+         foldr1 (<|>)
+                (map (\style ->
+                        fmap (const style)
+                             (constant (styleName style)))
+                     styles)))
