diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 ---
-title: SLOANE(1) Sloane User Manual | Version 1.8
-date: May 27, 2014
+title: SLOANE(1) Sloane User Manual | Version 1.8.2
+date: July 3, 2014
 ---
 
 # NAME
@@ -12,7 +12,7 @@
 
 sloane [-a | --all | -k *keys* | --url] [-n *entries*] *search-terms* ...  
 sloane (--update | --version | --help)  
-sloane
+sloane [--invert]
 
 # DESCRIPTION
 
@@ -28,15 +28,15 @@
 
 If no search terms are specified the standard input is read
 line-by-line. In this mode the search is done locally against a
-downloaded list of known sequences. If the sequence is in the OEIS, then
+downloaded list of known sequences. If the sequence is in OEIS, then
 it is returned to the standard output; if not, it is ignored. This way
 sloane can quickly filter out the sequences from the input that are in
-the OEIS. Assuming that *FILE* contains one sequence per line,
+OEIS. Assuming that *FILE* contains one sequence per line,
 
     sloane <FILE
 
-returns the subset of the sequences in *FILE* that are in the OEIS. To
-also look-up the names of those sequences in the OEIS one could, for
+returns the subset of the sequences in *FILE* that are in OEIS. To
+also look-up the names of those sequences in OEIS one could, for
 instance, run
 
     sloane <FILE | xargs -L1 --verbose sloane
@@ -58,6 +58,9 @@
 -n *entries*
 :   Fetch at most this many entries (default: 5)
 
+--invert
+:   When used as a filter, return sequences *not* in OEIS
+
 --update
 :   Update the local sequence cache
 
@@ -95,7 +98,7 @@
     firefox `sloane --url -n 3 "(2+2)-free posets"`
 
 In the final example the local cache is used to filter out sequences
-from the standard input that are in the OEIS:
+from the standard input that are in OEIS:
 
     sloane <<END
     1,2,3,6,11,23,47,106,235           # Comma separated integers
diff --git a/sloane.1 b/sloane.1
--- a/sloane.1
+++ b/sloane.1
@@ -1,4 +1,4 @@
-.TH "SLOANE" "1" "May 27, 2014" "Sloane User Manual" "Version 1.8"
+.TH "SLOANE" "1" "July 3, 2014" "Sloane User Manual" "Version 1.8.2"
 .SH NAME
 .PP
 sloane \- a command line interface to Sloane\[aq]s On\-Line Encyclopedia
@@ -14,7 +14,7 @@
 .PD 0
 .P
 .PD
-sloane
+sloane [\-\-invert]
 .SH DESCRIPTION
 .PP
 The sloane command searches Sloane\[aq]s On\-Line Encyclopedia of
@@ -37,10 +37,10 @@
 line\-by\-line.
 In this mode the search is done locally against a downloaded list of
 known sequences.
-If the sequence is in the OEIS, then it is returned to the standard
-output; if not, it is ignored.
+If the sequence is in OEIS, then it is returned to the standard output;
+if not, it is ignored.
 This way sloane can quickly filter out the sequences from the input that
-are in the OEIS.
+are in OEIS.
 Assuming that \f[I]FILE\f[] contains one sequence per line,
 .IP
 .nf
@@ -49,9 +49,8 @@
 \f[]
 .fi
 .PP
-returns the subset of the sequences in \f[I]FILE\f[] that are in the
-OEIS.
-To also look\-up the names of those sequences in the OEIS one could, for
+returns the subset of the sequences in \f[I]FILE\f[] that are in OEIS.
+To also look\-up the names of those sequences in OEIS one could, for
 instance, run
 .IP
 .nf
@@ -84,6 +83,11 @@
 .RS
 .RE
 .TP
+.B \-\-invert
+When used as a filter, return sequences \f[I]not\f[] in OEIS
+.RS
+.RE
+.TP
 .B \-\-update
 Update the local sequence cache
 .RS
@@ -148,7 +152,7 @@
 .fi
 .PP
 In the final example the local cache is used to filter out sequences
-from the standard input that are in the OEIS:
+from the standard input that are in OEIS:
 .IP
 .nf
 \f[C]
diff --git a/sloane.cabal b/sloane.cabal
--- a/sloane.cabal
+++ b/sloane.cabal
@@ -1,5 +1,5 @@
 Name:                sloane
-Version:             1.8
+Version:             1.8.2
 Synopsis:            A command line interface to Sloane's On-Line Encyclopedia of Integer Sequences
 Description:         A command line interface to Sloane's On-Line Encyclopedia of Integer Sequences.
                      For usage see <http://github.com/akc/sloane>.
@@ -20,7 +20,16 @@
 
 Executable sloane
   Main-is:             sloane.hs
-  Build-depends:       base >=3 && <5, optparse-applicative >=0.9, HTTP >=4000.0.9, network >=2.4,
-                       bytestring >=0.9, ansi-terminal >=0.6, terminal-size >=0.2,
-                       filepath >=1.3, directory >=1.2, stringsearch >=0.3,
-                       zlib >=0.5, time >=1.4
+  ghc-options:         -Wall
+  Build-depends:       base >=3 && <5,
+                       optparse-applicative >=0.9,
+                       HTTP >=4000.0.9,
+                       network >=2.4,
+                       bytestring >=0.9,
+                       text >=1.1,
+                       ansi-terminal >=0.6,
+                       terminal-size >=0.2,
+                       filepath >=1.3,
+                       directory >=1.2,
+                       zlib >=0.5,
+                       time >=1.4
diff --git a/sloane.hs b/sloane.hs
--- a/sloane.hs
+++ b/sloane.hs
@@ -4,11 +4,14 @@
 -- License     : BSD-3
 --
 import qualified Codec.Compression.GZip       as GZip
-import           Control.Monad                (unless, when)
-import qualified Data.ByteString.Char8        as B
-import qualified Data.ByteString.Lazy.Char8   as BL
-import qualified Data.ByteString.Lazy.Search  as Search
-import           Data.Maybe                   (fromJust, maybe)
+import           Control.Monad                (unless, when, liftM2)
+import qualified Data.ByteString              as B
+import qualified Data.ByteString.Lazy         as BL
+import           Data.Text                    (Text)
+import qualified Data.Text                    as T
+import qualified Data.Text.IO                 as IO
+import           Data.Text.Encoding           (decodeUtf8)
+import           Data.Maybe                   (fromJust)
 import           Data.Time                    (diffUTCTime, getCurrentTime)
 import           Network.HTTP
 import           Network.URI                  (parseURI)
@@ -17,7 +20,7 @@
 import           System.Console.Terminal.Size (Window (..), size)
 import           System.Directory
 import           System.FilePath              ((</>))
-import           System.IO                    (stderr, stdin)
+import           System.IO                    (stderr)
 
 type OEISEntries = [String]
 type ANumbers = [String]
@@ -25,25 +28,28 @@
 type Keys = String
 
 data Args = Args
-    { all    :: Bool
-    , keys   :: String
-    , limit  :: Int
-    , update :: Bool
-    , url    :: Bool
-    , ver    :: Bool
-    , terms  :: [String]
-    }
+    Bool     -- a: Print all fields?
+    String   -- k: Keys of fields to print
+    Int      -- n: Fetch at most this many entries
+    Bool     -- invert: Return sequences NOT in OEIS
+    Bool     -- update: Update the local sequence cache
+    Bool     -- url: Print URLs of found entries
+    Bool     -- version
+    [String] -- search terms
 
-version   = "sloane 1.8"
+name, oeisHost, oeisURL, cacheDir, cacheFile, cacheURL :: String
 
+name = "sloane 1.8.2"
+
 oeisHost  = "http://oeis.org/"
 oeisURL   = oeisHost ++ "search?fmt=text"
-oeisKeys  = "ISTUVWXNDHFYAOEeptoKC"
 
 cacheDir  = ".sloane"
 cacheFile = "stripped.gz"
 cacheURL  = oeisHost ++ cacheFile
 
+msgDownloadingCache, msgCacheIsUpToDate, msgNoCache, msgOldCache :: String
+
 msgDownloadingCache = unlines
     [ "Downloading " ++ cacheURL
     , "This may take a minute or two ..."
@@ -73,15 +79,6 @@
   where
     uri' = fromJust $ parseURI uri
 
-updateCache :: FilePath -> IO ()
-updateCache home = do
-    let dir = home </> cacheDir
-    createDirectoryIfMissing False dir
-    put msgDownloadingCache
-    cache <- get cacheURL
-    B.writeFile (dir </> cacheFile) cache
-    put msgCacheIsUpToDate
-
 searchOEIS :: Int -> Query -> IO OEISEntries
 searchOEIS n s = trim `fmap` get uri
   where
@@ -101,14 +98,20 @@
 getWidth :: IO Int
 getWidth = maybe maxBound width `fmap` size
 
-put = B.putStr . B.pack
-putErr = B.hPutStr stderr . B.pack
-newline = B.putStrLn B.empty
+put :: String -> IO ()
+put = IO.putStr . T.pack
 
+putErr :: String -> IO ()
+putErr = IO.hPutStr stderr . T.pack
+
+newline :: IO ()
+newline = IO.putStrLn T.empty
+
 putEntries :: Int -> OEISEntries -> IO ()
-putEntries width = mapM_ $ \line ->
+putEntries ncols = mapM_ $ \line -> do
     case words line of
-        [] -> newline
+        []  -> return ()
+        [w] -> put w -- Should never be reached
         (key:aNum:rest) -> do
             setSGR [ SetColor Foreground Dull Green ]
             put key
@@ -116,42 +119,48 @@
             put $ ' ' : aNum
             setSGR []
             let crop = if key == "S" then cropSeq else cropLine
-            put $ ' ' : crop width (unwords rest) ++ "\n"
-
-isInfixOf :: B.ByteString -> BL.ByteString -> Bool
-isInfixOf q = not . null . Search.indices q
+            put $ ' ' : crop ncols (unwords rest)
+    newline
 
-dropPreamble :: BL.ByteString -> BL.ByteString
-dropPreamble = BL.unlines . drop 4 . BL.lines
+updateCache :: FilePath -> IO ()
+updateCache home = do
+    createDirectoryIfMissing False dir
+    put msgDownloadingCache
+    get cacheURL >>= BL.writeFile (dir </> cacheFile)
+    put msgCacheIsUpToDate
+  where
+    dir = home </> cacheDir
 
-readCache :: FilePath -> IO BL.ByteString
+readCache :: FilePath -> IO Text
 readCache home = do
-    let name = home </> cacheDir </> cacheFile
-    updated <- doesFileExist name
+    updated <- doesFileExist fname
     if updated
         then do
-            c <- getCurrentTime
-            m <- getModificationTime name
-            let day = 60*60*24
-            let expired = c `diffUTCTime` m > 100*day
-            when expired $ putErr msgOldCache
-            (dropPreamble . GZip.decompress) `fmap` BL.readFile name
+            age <- liftM2 diffUTCTime getCurrentTime (getModificationTime fname)
+            when (age > 100*day) $ putErr msgOldCache
+            (dropPreamble . decompress) `fmap` BL.readFile fname
         else
             error msgNoCache
+  where
+    day = 60*60*24
+    fname = home </> cacheDir </> cacheFile
+    decompress = decodeUtf8 . B.concat . BL.toChunks . GZip.decompress
+    dropPreamble = T.unlines . drop 4 . T.lines
 
-seqs :: B.ByteString -> [B.ByteString]
-seqs = filter (not . B.null) . map mkSeq . B.lines
+seqs :: Text -> [Text]
+seqs = filter (not . T.null) . map mkSeq . T.lines
   where
     mkSeq = normalize . dropComment
-    dropComment = B.takeWhile (/= '#')
-    normalize   = B.intercalate (B.pack ",") . B.words . clean . B.map tr
+    dropComment = T.takeWhile (/= '#')
+    normalize   = T.intercalate (T.pack ",") . T.words . clean . T.map tr
     tr c  = if c `elem` ";," then ' ' else c
-    clean = B.filter (\c -> B.elem c (B.pack " 0123456789-"))
+    clean = T.filter (`elem` " 0123456789-")
 
-filterSeqs :: FilePath -> IO ()
-filterSeqs home = do
+filterSeqs :: Bool -> FilePath -> IO ()
+filterSeqs invert home = do
     cache <- readCache home
-    B.getContents >>= mapM_ B.putStrLn . filter (`isInfixOf` cache) . seqs
+    let f q = (if invert then not else id) (q `T.isInfixOf` cache)
+    IO.getContents >>= mapM_ IO.putStrLn . filter f . seqs
 
 args :: Parser Args
 args = Args
@@ -166,19 +175,22 @@
        <> metavar "N"
        <> value 5
        <> help "Fetch at most this many entries [default: 5]" )
+    <*> switch
+        ( long "invert"
+       <> help "When used as a filter, return sequences NOT in OEIS" )
     <*> switch (long "update" <> help "Update the local sequence cache")
     <*> switch (long "url" <> help "Print URLs of found entries")
     <*> switch (hidden <> long "version")
     <*> many (argument str (metavar "TERMS..."))
 
 sloane :: Args -> IO ()
-sloane (Args all keys n update url True terms) = put version >> newline
-sloane (Args all keys n True   url ver  terms) = getHomeDirectory >>= updateCache
-sloane (Args all keys n update url ver  []   ) = getHomeDirectory >>= filterSeqs
-sloane (Args all keys n update url ver  terms) = do
+sloane (Args _ _    _ _   _    _   True _ ) = put name >> newline
+sloane (Args _ _    _ _   True _   _    _ ) = getHomeDirectory >>= updateCache
+sloane (Args _ _    _ inv _    _   _    []) = getHomeDirectory >>= filterSeqs inv
+sloane (Args a keys n _   _    url _    ts) = do
     ncols <- getWidth
-    hits  <- searchOEIS n (unwords terms)
-    let pick = if all then id else select keys
+    hits  <- searchOEIS n (unwords ts)
+    let pick = if a then id else select keys
     unless (null hits) $ do
         newline
         if url
@@ -186,6 +198,7 @@
             else putEntries (ncols - 10) (pick hits)
         newline
 
-main = execParser (info (h <*> args) (fullDesc <> header version)) >>= sloane
+main :: IO ()
+main = execParser (info (h <*> args) (fullDesc <> header name)) >>= sloane
   where
     h = abortOption ShowHelpText $ hidden <> long "help"
