Main.hs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Main where
  3. import qualified Data.Text as T
  4. import Lens.Family
  5. import qualified System.Console.GetOpt as Opt
  6. import qualified System.Environment as Sys
  7. import qualified System.Exit as Sys
  8. import qualified Charter as C
  9. data Option
  10. = AddBinary T.Text
  11. | SetCategory T.Text
  12. | SetSynopsis T.Text
  13. | SetDescription T.Text
  14. | SetLicense T.Text
  15. | SetRoot T.Text
  16. | AddMod T.Text
  17. | AddDep T.Text
  18. | AddUsualDeps
  19. deriving (Eq, Show, Ord)
  20. options :: [Opt.OptDescr Option]
  21. options =
  22. [ Opt.Option ['b'] ["bin"]
  23. (Opt.ReqArg (AddBinary . T.pack) "PROGRAM NAME")
  24. "Add another binary target to this Cabal file"
  25. , Opt.Option ['m'] ["module"]
  26. (Opt.ReqArg (AddMod . T.pack) "MODULE NAME")
  27. "Add another library module to this Cabal file"
  28. , Opt.Option ['r'] ["root"]
  29. (Opt.ReqArg (SetRoot . T.pack) "DIRECTORY")
  30. "Set the root directory for this project"
  31. , Opt.Option ['c'] ["category"]
  32. (Opt.ReqArg (SetCategory . T.pack) "CATEGORY")
  33. "Set the category for this project"
  34. , Opt.Option ['s'] ["synopsis"]
  35. (Opt.ReqArg (SetSynopsis . T.pack) "SYNOPSIS")
  36. "Set the synopsis for this project"
  37. , Opt.Option ['d'] ["description"]
  38. (Opt.ReqArg (SetDescription . T.pack) "DESCRIPTION")
  39. "Set the description for this project"
  40. , Opt.Option ['l'] ["license"]
  41. (Opt.ReqArg (SetLicense . T.pack) "LICENSE")
  42. "Set the license for this project"
  43. , Opt.Option ['a'] ["add-dep"]
  44. (Opt.ReqArg (AddDep . T.pack) "PACKAGE")
  45. "Add a dependency to this application"
  46. , Opt.Option ['A'] ["add-usual-deps"]
  47. (Opt.NoArg AddUsualDeps)
  48. "Add the typical set of dependencies to this application"
  49. ]
  50. usageInfo :: String
  51. usageInfo = Opt.usageInfo header options
  52. where header = "Usage: charter (quick|executable|library) [name]"
  53. process :: [Option] -> C.Project -> Either String C.Project
  54. process opts p = foldl (>>=) (return p) (map go opts)
  55. where
  56. go (AddBinary n) proj =
  57. return $ proj & C.binDetails %~ (C.mkBinary n :)
  58. go (AddMod m) proj =
  59. return $ proj & C.libDetails %~ fmap (& C.libMods %~ (m :))
  60. go (SetCategory s) proj =
  61. return $ proj & C.projectDetails . C.projectCategory .~ Just s
  62. go (SetSynopsis s) proj =
  63. return $ proj & C.projectDetails . C.projectSynopsis .~ Just s
  64. go (SetDescription s) proj =
  65. return $ proj & C.projectDetails . C.projectDescription .~ Just s
  66. go (SetLicense license) proj
  67. | not (license `elem` C.validLicenses) =
  68. Left $ concat [ "Unknown license: `"
  69. , T.unpack license
  70. , "'\n\nValid Cabal licenses include:\n - "
  71. , T.unpack (T.intercalate "\n - " C.validLicenses)
  72. ]
  73. | otherwise =
  74. return $ proj & C.projectDetails . C.projectLicense .~ Just license
  75. go (SetRoot _) proj = return proj
  76. go (AddDep dep) proj =
  77. return $ proj & C.binDetails %~ fmap (& C.execDeps %~ (dep :))
  78. & C.libDetails %~ fmap (& C.libDeps %~ (dep :))
  79. go (AddUsualDeps) proj =
  80. return $ proj & C.binDetails %~ fmap (& C.execDeps %~ (C.usualDeps ++))
  81. & C.libDetails %~ fmap (& C.libDeps %~ (C.usualDeps ++))
  82. setupProject :: String -> String -> IO C.Project
  83. setupProject typ name = do
  84. details <- C.projectDefaults (T.pack name)
  85. case typ of
  86. "quick" -> return (C.quickBin details)
  87. "executable" -> return (C.projectBin details)
  88. "library" -> return (C.library details)
  89. _ -> Sys.die ("unknown project type: " ++ typ ++ "\n" ++ usageInfo)
  90. main :: IO ()
  91. main = do
  92. args <- Sys.getArgs
  93. case Opt.getOpt Opt.Permute options args of
  94. (os, [typ, name], []) -> do
  95. proj <- process os <$> setupProject typ name
  96. case proj of
  97. Right p -> C.createProject p
  98. Left err -> Sys.die err
  99. (_, _, errs) -> do
  100. mapM_ putStrLn errs
  101. Sys.die usageInfo