+ prompt (xs +++ " (y/n):") getOneText v
+
+listPrompt :: Text -> [Text] -> IO Text
+listPrompt xs options = do
+ putStrLn $ xs +++ "\n\n" +++ cue
+ prompt ("Make your selection " +++ validRange +++ ": ") getOneText validator where
+ cue = unlines $ map (\x -> (pack . show $ fst x) +++ ") " +++ snd x) themeList
+ validator x = if choice > 0 && choice <= upper
+ then Right (fromJust (lookup choice themeList))
+ else Left $ "\nPick a valid number " +++ validRange where
+ choice = read . unpack $ x
+ themeList = (zip [1..] options)
+ validRange = "(1-" +++ (pack . show $ upper) +++ ")"
+ upper = length themeList
+
+dependantTextPrompt :: Text -> Text -> IO (Maybe (Text, Text))
+dependantTextPrompt xs1 xs2 = subPrompt (textPrompt xs1) (nonEmptyTextPrompt xs2) (not . null)
+
+dependantYornTextPrompt :: Text -> Text -> IO (Maybe (Bool, Text))
+dependantYornTextPrompt xs1 xs2 = subPrompt (yornPrompt xs1) (nonEmptyTextPrompt xs2) (id)
+
+entryPrompt = subPrompt entryNamePrompt videoPrompt (not . null) where
+ entryNamePrompt = nonEmptyTextPrompt "Name for this entry: "
+ videoPrompt = dependantTextPrompt "Video ID (leave blank to skip): " "Local video filename: "
+
+initPrompt :: [Text] -> IO [(String, Text)]
+initPrompt themes = fmap (zip ["projectName", "description", "theme"]) $ sequence prompts where
+ prompts = [
+ nonEmptyTextPrompt "Enter a name for your project: ",
+ nonEmptyTextPrompt "Enter a short description for your project: ",
+ listPrompt "Which theme would you like to use?" themes
+ ]