@@ -0,0 +1,96 @@
1+--------------------------------------------------------------------------------
7+--------------------------------------------------------------------------------
8+import Control.Arrow (first)
9+import Control.Monad (forM_)
10+import Data.Char (isAlphaNum, isNumber)
11+import Data.List (foldl')
12+import Data.List (intercalate, isPrefixOf)
13+import Data.Version (Version (..))
14+import System.Directory (canonicalizePath, copyFile)
15+import System.Environment (getArgs, getProgName)
16+import System.Exit (exitFailure)
17+import System.FilePath (splitDirectories, (</>))
20+--------------------------------------------------------------------------------
21+import Hakyll.Core.Util.File
25+--------------------------------------------------------------------------------
28+ progName <- getProgName
30+ srcDir <- getDataFileName "example"
31+ files <- getRecursiveContents (const $ return False) srcDir
34+ -- When the argument begins with hyphens, it's more likely that the user
35+ -- intends to attempt some arguments like ("--help", "-h", "--version", etc.)
36+ -- rather than create directory with that name.
37+ -- If dstDir begins with hyphens, the guard will prevent it from creating
38+ -- directory with that name so we can fall to the second alternative
39+ -- which prints a usage info for user.
40+ [dstDir] | not ("-" `isPrefixOf` dstDir) -> do
41+ forM_ files $ \file -> do
42+ let dst = dstDir </> file
43+ src = srcDir </> file
44+ putStrLn $ "Creating " ++ dst
48+ name <- makeName dstDir
49+ let cabalPath = dstDir </> name ++ ".cabal"
50+ putStrLn $ "Creating " ++ cabalPath
51+ createCabal cabalPath name
53+ putStrLn $ "Usage: " ++ progName ++ " <directory>"
56+-- | Figure out a good cabal package name from the given (existing) directory
58+makeName :: FilePath -> IO String
60+ canonical <- canonicalizePath dstDir
61+ return $ case safeLast (splitDirectories canonical) of
62+ Nothing -> fallbackName
63+ Just "/" -> fallbackName
64+ Just x -> repair (fallbackName ++) id x
66+ -- Package name repair code comes from
67+ -- cabal-install.Distribution.Client.Init.Heuristics
68+ repair invalid valid x = case dropWhile (not . isAlphaNum) x of
69+ "" -> repairComponent ""
70+ x' -> let (c, r) = first repairComponent $ break (not . isAlphaNum) x'
72+ where repairComponent c | all isNumber c = invalid c
73+ | otherwise = valid c
74+ repairRest = repair id ('-' :)
75+ fallbackName = "site"
77+ safeLast = foldl' (\_ x -> Just x) Nothing
79+createCabal :: FilePath -> String -> IO ()
80+createCabal path name = do
81+ writeFile path $ unlines [
84+ , "build-type: Simple"
85+ , "cabal-version: >= 1.10"
88+ , " main-is: site.hs"
89+ , " build-depends: base == 4.*"
90+ , " , hakyll == " ++ version' ++ ".*"
91+ , " ghc-options: -threaded"
92+ , " default-language: Haskell2010"
95+ -- Major hakyll version
96+ version' = intercalate "." . take 2 . map show $ versionBranch version