3 import Data.List (intercalate)
4 import Data.String hiding (unlines)
5 import Data.Text hiding (map, init, length, splitAt)
6 import Data.Text.IO (putStrLn, putStr, writeFile)
7 import Data.Text.Lazy (toStrict)
8 import Data.Text.Template
9 import Data.Time.Clock.POSIX
11 import Prelude hiding (putStrLn, putStr, init, unlines, writeFile)
13 import System.Directory
14 import System.Directory (doesFileExist)
15 import System.Environment
17 import System.File.Tree hiding (map, mapM, mapM_)
20 import Text.JSON.Generic
24 main = getArgs >>= parse
26 continueIfValidProject :: IO () -> IO ()
27 continueIfValidProject nextfn = do
28 jsonExists <- doesFileExist "xyz.json"
31 else putStrLn "This does not appear to be a valid project directory"
35 dirExists <- doesFileExist "xyz.json"
37 then putStrLn "Project already initialised"
38 else do home <- getHomeDirectory
39 themes <- allFilesIn $ home ++ "/.xyz/themes"
40 projectSpec <- initPrompt (map pack themes)
41 createDirectory "entries"
42 writeFile "xyz.json" . pack . encode . toJSObject $ projectSpec
43 putStrLn "\n\nInitialised empty project"
47 fileExists <- doesFileExist "xyz.json"
50 files <- allFilesIn "entries"
51 home <- getHomeDirectory
52 config <- readFile "xyz.json"
53 writeOutProject (decodeJSON config :: ProjectConfig) files >> putStrLn "Build successful"
54 else putStrLn "This does not appear to be a valid project directory"
58 homeDir <- getHomeDirectory
59 entrySpec <- entryPrompt
60 entryNum <- fmap (show . (+1) . length) $ allFilesIn "entries"
61 stamp <- fmap (pack . show . round) getPOSIXTime
62 videoTemplate <- readFile (homeDir ++ "/.xyz/entry-video.txt") >>= return . template . fromString
63 normalTemplate <- readFile (homeDir ++ "/.xyz/entry.txt") >>= return . template . fromString
65 let rawEntry = case entrySpec of
66 Just (title, videoSpec) -> do
67 let baseContext = [("timestamp", stamp), ("title", title)]
69 Just (videoId, videoFilename) -> (title, toStrict . render videoTemplate $ context $ baseContext ++ [("videoid", videoId), ("videofilename", videoFilename)])
70 Nothing -> (title, toStrict . render normalTemplate $ context baseContext)
72 let fileName = "entries/" ++ entryNum ++ "-" ++ (unpack . slugify $ fst rawEntry) ++ ".txt"
73 writeFile fileName $ snd rawEntry
75 callCommand $ "nano " ++ fileName
79 True -> do callCommand . unpack $ "git add . && git commit -m \"" +++ (fst rawEntry) +++ "\" && git push"
82 putStrLn "Thanks for using xyz!"
85 usage = putStr . ununlines $ [
86 "usage: xyz <command>",
87 "Commands:", unlines [
88 "\tinit\t\tInitialise a new site",
89 "\tbuild\t\tBuild the site",
90 "\tentry\t\tInitialise an entry"
94 parse ["init"] = init >> exitSuccess
95 parse ["build"] = continueIfValidProject build >> exitSuccess
96 parse ["entry"] = continueIfValidProject entry >> exitSuccess
97 parse [_] = usage >> exit
98 parse [] = usage >> exit
100 exit = exitWith ExitSuccess