module Main where import Prelude hiding (id, putStrLn) import Data.Monoid ((<>)) import Data.Text (intercalate) import Data.Text.IO (putStrLn) import Data.Version (showVersion) import Database.SQLite.Simple import Options.Applicative import Paths_pinboard_notes_backup (version) import Pinboard import System.Exit (exitFailure) import Text.PrettyPrint.ANSI.Leijen (Doc, vsep) import Types import Utils (pluralize, putStrLnErr) -- * Command line parsing data ProgramOptions = ProgramOptions { o_apiToken :: String , o_verbosity :: Verbosity , o_databasePath :: String } optionsParser :: Options.Applicative.Parser ProgramOptions optionsParser = ProgramOptions <$> strOption (short 't' <> long "token" <> metavar "TOKEN" <> help tokenHelp) <*> flag Standard Verbose (short 'v' <> long "verbose" <> help verboseHelp) <*> argument str (metavar "FILE" <> help pathHelp) where tokenHelp = "Your API token (e.g. maciej:abc123456). " <> "You can find this at ." verboseHelp = "Display detailed progress information." pathHelp = "Filename of the SQLite database where your notes will be stored. " <> "This file will be created if it does not already exist. " <> "Notes are always stored in a table called \"notes\"." addVersionOption :: Options.Applicative.Parser (a -> a) addVersionOption = infoOption ("pnbackup " <> showVersion version) (long "version" <> help "Show the version number" <> hidden) footerText :: Doc footerText = vsep [ "For more information, see \"man pnbackup\"." , "" , "Copyright © 2016–2017, 2019 Benjamin D. Esham" , "" , "License GPLv3+: GNU GPL version 3 or later ." , "This is free software: you are free to change and redistribute it." , "There is NO WARRANTY, to the extent permitted by law." ] commandLineOptions :: ParserInfo ProgramOptions commandLineOptions = info (addVersionOption <*> helper <*> optionsParser) parserInfo where parserInfo = fullDesc <> header "pnbackup -- Back up the notes you've saved to Pinboard" <> footerDoc (Just footerText) -- * Main main :: IO () main = execParser commandLineOptions >>= main' main' :: ProgramOptions -> IO () main' (ProgramOptions apiToken verbosity databasePath) = do conn <- open databasePath execute_ conn createTableQuery result <- runPinboard apiToken verbosity $ backUpNotes conn case result of Left err -> putStrLnErr ("pnbackup: " <> err) >> exitFailure Right result' -> displayResult result' createTableQuery :: Query createTableQuery = mconcat [ "CREATE TABLE IF NOT EXISTS notes " , "(id TEXT NOT NULL UNIQUE, " , "title TEXT NOT NULL, " , "text TEXT NOT NULL, " , "hash TEXT NOT NULL, " , "created DATETIME NOT NULL, " , "updated DATETIME NOT NULL)" ] displayResult :: ApplicationResult -> IO () displayResult (ApplicationResult upToDate updated new deleted) = do putStrLn $ intercalate ", " [ updatedString , newString , deletedString , upToDateString ] <> "." where upToDateString = pluralize "note already up-to-date" "notes already up-to-date" upToDate updatedString = pluralize "note updated" "notes updated" updated newString = pluralize "new note" "new notes" new deletedString = pluralize "note deleted" "notes deleted" deleted