diff --git a/scat.cabal b/scat.cabal
--- a/scat.cabal
+++ b/scat.cabal
@@ -10,13 +10,13 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             1.0.0.0
+version:             1.0.1.0
 
 -- A short (one-line) description of the package.
 synopsis:            Generates unique passwords for various websites from a single password.
 
 -- A longer description of the package.
--- description:         
+description:         Flexible password generator. For each service, passwords are generated deterministically from a main password and a code. Internally, Scrypt is used to obtain the hash generating the passwords.
 
 -- The license under which the package is released.
 license:             BSD3
@@ -50,6 +50,10 @@
 data-dir: lists
 
 data-files: *.txt 
+
+source-repository head
+  type: git
+  location: https://github.com/redelmann/scat
 
 executable scat
   -- .hs or .lhs file containing the Main module.
diff --git a/src/Scat.hs b/src/Scat.hs
--- a/src/Scat.hs
+++ b/src/Scat.hs
@@ -4,8 +4,7 @@
 module Main (main) where
 
 import Data.Monoid
-import Data.ByteString (ByteString)
-import Data.ByteString (unpack)
+import Data.ByteString (ByteString, unpack)
 import qualified Data.ByteString.Char8 as C
 import System.IO
 import System.Exit
@@ -41,7 +40,7 @@
 shouldErase :: Visibility -> Bool
 shouldErase Shown  = False
 shouldErase Hidden = False
-shouldErase Erased = True 
+shouldErase Erased = True
 
 {- | Generates a password, given a input password,
      a service name (category, website, etc.),
@@ -60,8 +59,20 @@
     pw <- getPassword
     c  <- getCode
     printVerbose "Generated password:\n"
-    liftIO $ putStrLn $ evalBuilder s $ scatter k pw c
+    showGenerated $ evalBuilder s $ scatter k pw c
 
+-- | Prints out the generated password.
+showGenerated :: String -> Scat ()
+showGenerated gen = do
+    v <- fmap verbose ask
+    a <- fmap ansi ask
+    let ok = v && a
+    liftIO $ do
+        when ok $ setSGR [SetSwapForegroundBackground True]
+        putStrLn gen
+        when ok $ setSGR [SetSwapForegroundBackground False]
+
+
 -- | Prints, if the verbosity level allows it.
 printVerbose :: String -> Scat ()
 printVerbose str = do
@@ -105,7 +116,9 @@
         (hSetEcho stdin $ shouldShow vis)
         (hSetEcho stdin old)
         C.getLine
-    when (shouldErase vis) $ liftIO $ do
+    v <- fmap verbose ask
+    a <- fmap ansi ask
+    when (shouldErase vis && a && v) $ liftIO $ do
         cursorUpLine 1
         cursorForward $ length str
         clearFromCursorToScreenEnd
@@ -149,6 +162,16 @@
 
         -- PIN.
         'p' : 'i' : 'n' : xs | [(n, "")] <- reads xs -> return $ pin n
+
+        -- PIN with default size.
+        "pin" -> return $ pin 6
+
+        -- Pattern lock
+        'l' : 'o' : 'c' : 'k' : xs | [(n, "")] <- reads xs -> return $
+            androidPatternLock n
+
+        -- Default size of pattern lock
+        "lock" -> return $ androidPatternLock 9
 
         -- Passphrase using Diceware's list.
         "diceware" -> liftIO diceware
diff --git a/src/Scat/Options.hs b/src/Scat/Options.hs
--- a/src/Scat/Options.hs
+++ b/src/Scat/Options.hs
@@ -13,6 +13,7 @@
     , schema
     , verbose
     , confirm
+    , ansi
 
     -- * Execution
     , getOptions
@@ -37,6 +38,8 @@
     -- ^ Verbosity. If false, do not print anything but the generated password.
     , confirm  :: Bool
     -- ^ Indicates if the password must be confirmed.
+    , ansi     :: Bool
+    -- ^ Indicates if ANSI escape sequences can be used.
     }
 
 -- | Parses the arguments from the command line.
@@ -45,7 +48,9 @@
   where
     opts = info (helper <*> options)
         (fullDesc
-        <> progDesc "Safely generate passwords derived from a unique password and code."
+        <> progDesc (unwords
+            [ "Safely generate passwords derived "
+            , "from a unique password and code." ])
         <> header "scat - a password scatterer")
 
 -- | Option parser.
@@ -83,3 +88,6 @@
           (short 'c'
         <> long "confirmation"
         <> help "Asks for password confirmation")
+    <*> flag True False
+          (long "noansi"
+        <> help "Do not use ANSI escape sequences to format output")
diff --git a/src/Scat/Schemas.hs b/src/Scat/Schemas.hs
--- a/src/Scat/Schemas.hs
+++ b/src/Scat/Schemas.hs
@@ -18,9 +18,12 @@
     -- * Pass phrases
     , pokemons
     , diceware
+
+    -- * Pattern lock
+    , androidPatternLock
     ) where
 
-import Data.List (intercalate)
+import Data.List (intercalate, (\\))
 import Data.Vector (Vector)
 import qualified Data.Vector as V
 import Data.Monoid
@@ -74,6 +77,61 @@
      Entropy of about @3.32 * n@ bits. -}
 pin :: Int -> Schema
 pin n = replicateM n digit
+
+
+-- | Generates an Android lock pattern, of specified length.
+androidPatternLock :: Int -> Schema
+androidPatternLock number = do
+    xs <- loop (min number (height * width)) []
+    return $ intercalate " - " $ map showPosition xs
+  where
+    -- Gets `n` points.
+    loop :: Int -> [(Int, Int)] -> Builder [(Int, Int)]
+    loop n xs | n <= 0 = return $ reverse xs
+    loop n xs = do
+        x <- oneOf $ possibilities xs
+        loop (n - 1) (x : xs)
+
+    -- Grid dimensions.
+    height = 3
+    width = 3
+
+    -- Text representation for a position.
+    showPosition (1, 1) = "center"
+    showPosition (i, j) = vshow i ++ hshow j
+      where
+        vshow 0 = "north"
+        vshow 1 = ""
+        vshow _ = "south"
+
+        hshow 0 = "west"
+        hshow 1 = ""
+        hshow _ = "east"
+
+    -- All positions.
+    allPositions = [(i, j) | i <- [0 .. height - 1], j <- [0 .. width - 1]]
+
+    {- Possible positions given a list of already used ones.
+       The head of the list is the last used position. -}
+    possibilities [] = allPositions
+    possibilities pps@(p : ps) = filter isPossible candidates
+      where
+        candidates = allPositions \\ pps
+
+        isPossible q = all (`elem` ps) $ interfere p q
+
+    -- The list of positions that are on the way between two positions.
+    interfere (i, j) (k, l) = do
+        r <- [1 .. steps - 1]
+        return (i + r * vstep, j + r * hstep)
+      where
+        vdiff = k - i
+        hdiff = l - j
+
+        steps = gcd vdiff hdiff
+
+        vstep = vdiff `div` steps
+        hstep = hdiff `div` steps
 
 {- | Generates a password with 4 of the original Pokemons and their level.
      Entropy of about 55.5 bits. -}
