clippings-0.2.0: examples/Clippings2TSV.hs
{-# LANGUAGE RecordWildCards, LambdaCase #-}
module Main where
import Prelude hiding (putStr)
import Control.Applicative ((<$>))
import Data.Bifunctor (Bifunctor(bimap))
import Data.ByteString.Lazy (ByteString)
import Data.ByteString.Lazy.Char8 (putStr)
import Data.Char (ord)
import Data.Csv (ToRecord(..), EncodeOptions(..), encodeWith, defaultEncodeOptions, toField, record)
import Data.Functor.Infix ((<$$>))
import Data.Maybe (fromMaybe, catMaybes)
import Data.Monoid ((<>))
import System.Environment (getArgs)
import System.Exit (exitSuccess, exitFailure)
import System.IO (hPutStr, stderr)
import Text.Kindle.Clippings (Clipping(..), Document(..), Content(..), readClippings)
import Text.Parsec (parse)
data Card = Card { question :: String, answer :: String }
instance ToRecord Card where
toRecord (Card q a) = record $ map toField [q,a]
class ToCard a where
toCard :: a -> Maybe Card
instance ToCard Clipping where
toCard c@Clipping{..}
| not (isHighlight c) = Nothing
| null (show content) = Nothing
| otherwise = Just $ Card content' author'
where author' = fromMaybe "[clippings2tsv]" $ (" - " <>) <$> author document
content' = \case { '\n' -> ' '; chr -> chr; } <$> show content
isHighlight :: Clipping -> Bool
isHighlight Clipping{..} = case content of
Highlight _ -> True
_ -> False
getClippings :: String -> Either String [Clipping]
getClippings = bimap show catMaybes
. parse readClippings []
encodeTabDelimited :: ToRecord a => [a] -> ByteString
encodeTabDelimited = encodeWith $ defaultEncodeOptions
{ encDelimiter = fromIntegral $ ord '\t' }
renderClippings :: [Clipping] -> ByteString
renderClippings = encodeTabDelimited . catMaybes . fmap toCard
main :: IO ()
main = head <$> getArgs >>= getClippings <$$> readFile >>= \case
Left err -> hPutStr stderr err >> exitFailure
Right cs -> putStr (renderClippings cs) >> exitSuccess