diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+
+all: build 
+
+clean:
+	runhaskell Setup.hs clean
+
+configure: Setup.hs denominate.cabal *.hs
+	runhaskell Setup.hs configure --user --prefix=${HOME}
+
+build: configure
+	runhaskell Setup.hs build
+
+haddock: configure build
+	runhaskell Setup.hs haddock
+	find dist/doc/html -name '*.html' -exec \
+		sed -i -r 's_/usr/share/doc/ghc-[^/]+/html/libraries/_http://www.haskell.org/ghc/docs/latest/html/libraries/_g' {} \;
+
+install:  configure build
+	runhaskell Setup.hs install
+
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -6,7 +6,7 @@
 import System.Process
 
 main :: IO ()
-main = defaultMainWithHooks (defaultUserHooks { runTests = test })
+main = defaultMainWithHooks (simpleUserHooks { runTests = test })
 
 test :: Args -> Bool -> PackageDescription -> LocalBuildInfo -> IO ()
 test _ _ _ _ = runCommand commandStr >>= waitForProcess >> return ()
diff --git a/denominate.cabal b/denominate.cabal
--- a/denominate.cabal
+++ b/denominate.cabal
@@ -1,40 +1,44 @@
-name:              denominate
-version:           0.4.1
-cabal-version:     >= 1.2
-license:           BSD3
-license-file:      LICENSE.txt
-author:            Calvin Smith
-copyright:         (c) Calvin Smith
-maintainer:        cs-haskell@protempore.net
-homepage:          http://protempore.net/denominate/
-category:          System
-stability:         Experimental
-synopsis:          Functions supporting bulk file and directory name 
-                   normalization.
-description:       Denominate provides a main program for performing bulk 
-                   file and directory renaming, using a built-in filename
-                   converter or user-defined converters.
-                   .
-                   Additionally, it provides a module that exposes some 
-                   functions related to renaming and name normalization 
-                   that might be otherwise useful.
+name:               denominate
+version:            0.4.2
+synopsis:           Functions supporting bulk file and directory name
+                    normalization.
+description:        Denominate is a simple program and an associated library
+                    supporting bulk file and directory name normalization.
+                    .
+                    If you've ever spent a long time changing filenames to
+                    get rid of whitespace or convert periods and underscores
+                    to hyphens, you know why it exists.
 
+license:            BSD3
+license-file:       LICENSE.txt
+category:           System
+copyright:          (c) Calvin Smith
+author:             Calvin Smith
+maintainer:         cs-haskell@protempore.net
+stability:          Experimental
+homepage:           http://protempore.net/denominate/
+build-type:         Simple
+cabal-version:      >= 1.2
+tested-with:        GHC==6.6.1 GHC==6.8.2
+extra-source-files: quickcheck Makefile
+extra-tmp-files:    hugsin
+
 flag small_base
-  description:     Choose the new smaller, split-up base package.
+  description:      Choose the new smaller, split-up base package.
 
 library
   exposed-modules: System.Denominate
   if flag(small_base)
-    build-depends: base >= 3, directory, filepath
+    build-depends:  base >= 3, directory, filepath
   else
-    build-depends: base < 3, filepath
-  ghc-options:     -O -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-orphans
+    build-depends:  base < 3, filepath
+  ghc-options:      -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-orphans
 
 executable denominate
-  main-is:         Main.hs
+  main-is:          Main.hs
   if flag(small_base)
-    build-depends: base >= 3, directory, filepath
+    build-depends:  base >= 3, directory, filepath
   else
-    build-depends: base < 3, filepath
-  ghc-options:     -O -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-orphans
+    build-depends:  base < 3, filepath
+  ghc-options:      -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-orphans
 
diff --git a/quickcheck b/quickcheck
new file mode 100644
--- /dev/null
+++ b/quickcheck
@@ -0,0 +1,54 @@
+#!/usr/bin/runhugs
+-- 	$Id: quickcheck,v 1.4 2003/01/08 15:09:22 shae Exp $	
+-- This file defines a command
+--      quickCheck <options> <files>
+-- which invokes quickCheck on all properties defined in the files given as
+-- arguments, by generating an input script for hugs and then invoking it.
+-- quickCheck recognises the options
+--      +names     print the name of each property before checking it
+--      -names     do not print property names (the default)
+-- Other options (beginning with + or -) are passed unchanged to hugs.
+--
+-- Change the first line of this file to the location of runhugs on your 
+-- system.
+-- Make the file executable.
+--
+-- TODO:
+-- someone on #haskell asked about supporting QC tests inside LaTeX, ex. \{begin} \{end}, how?
+-- add a verbosity switch that uses verboseCheck instead of quickCheck
+
+import System
+import List
+
+main :: IO ()
+main = do as<-getArgs
+          sequence_ (map (process (filter isOption as)) 
+	                 (filter (not.isOption) as))
+
+-- ugly hack for .lhs files, is there a better way?
+unlit [] = []
+unlit x  = if (head x) == '>' then (tail x) else x
+
+process opts file =
+       let (namesOpt,opts') = getOption "names" "-names" opts in
+       do xs<-readFile file
+          let names = nub$ filter (\x -> (("> prop_" `isPrefixOf` x) || ("prop_" `isPrefixOf` x)))
+	                (map (fst.head.lex.unlit) (lines xs)) 
+          if null names then
+	      putStr (file++": no properties to check\n")
+	    else do writeFile "hugsin"$
+	              unlines ((":l "++file):
+	                       [(if namesOpt=="+names" then 
+			           "putStr \""++p++": \" >> "
+				 else "") ++
+				"Test.QuickCheck.quickCheckWith 500 5000 100 "++p | p<-names])
+	            system ("ghci -v0 "++options opts'++" <hugsin")
+	            return ()
+
+isOption xs = head xs `elem` "-+"
+
+options opts = unwords ["\""++opt++"\"" | opt<-opts]
+
+getOption name def opts = 
+  let opt = head [opt | opt<-opts++[def], isPrefixOf name (drop 1 opt)] in
+    (opt, filter (/=opt) opts)
