packages feed

hascard-0.6.0.2: src/Export.hs

{-# LANGUAGE TemplateHaskell #-}
module Export where

import Lens.Micro.Platform
import qualified Data.List.NonEmpty as NE
import Types
import Data.Either.Extra (mapRight)
import Data.List.Extra (replace)
import Data.List (intercalate, stripPrefix, tails, isPrefixOf)

data ExportOpts = ExportOpts
  { _optExportInput       :: String 
  , _optExportOutput      :: String
  , _optCardDelimiter     :: String 
  , _optQuestionDelimiter :: String 
  }

makeLenses ''ExportOpts

exportCards :: ExportOpts -> [Card] -> Either String String
exportCards opts = mapRight (intercalate (opts ^. optCardDelimiter)) 
                 . mapM (exportCard opts)

exportCard :: ExportOpts -> Card -> Either String String
exportCard opts (Definition {question=q, definition=d}) = Right $
  escape opts q <> (opts ^. optQuestionDelimiter) <> escape opts d
exportCard opts (OpenQuestion {question=q, perforated=p}) = Right $
  escape opts q <> (opts ^. optQuestionDelimiter) <> escape opts (fillPerforated p)
exportCard _ _ = Left "Only definition and open question cards can be exported."

fillPerforated :: Perforated -> String
fillPerforated = foldSentence id fSent . perforatedToSentence
  where fSent pre gaps post = pre <> concat (NE.intersperse "/" gaps) <> post

escape :: ExportOpts -> String -> String
escape opts s = if s `contains` (opts ^. optCardDelimiter) || s `contains` (opts ^. optQuestionDelimiter)
  then "\"" <> replace "\"" "\"\"" s <> "\""
  else s

contains :: Eq a => [a] -> [a] -> Bool
contains str substr = any (isPrefixOf substr) (tails str)