@@ -0,0 +1,96 @@
1+--------------------------------------------------------------------------------
2+module Main
3+ ( main
4+ ) where
5+
6+
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, (</>))
18+
19+
20+--------------------------------------------------------------------------------
21+import Hakyll.Core.Util.File
22+import Paths_hakyll
23+
24+
25+--------------------------------------------------------------------------------
26+main :: IO ()
27+main = do
28+ progName <- getProgName
29+ args <- getArgs
30+ srcDir <- getDataFileName "example"
31+ files <- getRecursiveContents (const $ return False) srcDir
32+
33+ case args of
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
45+ makeDirectories dst
46+ copyFile src dst
47+
48+ name <- makeName dstDir
49+ let cabalPath = dstDir </> name ++ ".cabal"
50+ putStrLn $ "Creating " ++ cabalPath
51+ createCabal cabalPath name
52+ _ -> do
53+ putStrLn $ "Usage: " ++ progName ++ " <directory>"
54+ exitFailure
55+
56+-- | Figure out a good cabal package name from the given (existing) directory
57+-- name
58+makeName :: FilePath -> IO String
59+makeName dstDir = do
60+ canonical <- canonicalizePath dstDir
61+ return $ case safeLast (splitDirectories canonical) of
62+ Nothing -> fallbackName
63+ Just "/" -> fallbackName
64+ Just x -> repair (fallbackName ++) id x
65+ where
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'
71+ in c ++ repairRest r
72+ where repairComponent c | all isNumber c = invalid c
73+ | otherwise = valid c
74+ repairRest = repair id ('-' :)
75+ fallbackName = "site"
76+
77+ safeLast = foldl' (\_ x -> Just x) Nothing
78+
79+createCabal :: FilePath -> String -> IO ()
80+createCabal path name = do
81+ writeFile path $ unlines [
82+ "name: " ++ name
83+ , "version: 0.1.0.0"
84+ , "build-type: Simple"
85+ , "cabal-version: >= 1.10"
86+ , ""
87+ , "executable site"
88+ , " main-is: site.hs"
89+ , " build-depends: base == 4.*"
90+ , " , hakyll == " ++ version' ++ ".*"
91+ , " ghc-options: -threaded"
92+ , " default-language: Haskell2010"
93+ ]
94+ where
95+ -- Major hakyll version
96+ version' = intercalate "." . take 2 . map show $ versionBranch version