{-# LANGUAGE OverloadedStrings #-}
module Poseidon.CLI.List (runList, ListOptions(..), ListEntity(..), RepoLocationSpec(..)) where
import Poseidon.BibFile (authorAbbrvString, parseAuthors)
import Poseidon.EntityTypes (HasNameAndVersion (..))
import Poseidon.Package (PackageReadOptions (..),
defaultPackageReadOptions,
getAllGroupInfo, getBibliographyInfo,
getExtendedIndividualInfo,
packagesToPackageInfos,
readPoseidonPackageCollection)
import Poseidon.ServerClient (AddColSpec (..), ApiReturnData (..),
ArchiveEndpoint (..),
BibliographyInfo (..),
ExtendedIndividualInfo (..),
GroupInfo (..), PackageInfo (..),
processApiResponse, qDefault)
import Poseidon.Utils (PoseidonIO, logInfo, logWarning)
import Control.Monad (forM_, when)
import Control.Monad.IO.Class (liftIO)
import Data.List (intercalate, nub, sortOn)
import Data.Maybe (catMaybes, fromMaybe)
import qualified Data.Text as T
import Data.Version (Version, showVersion)
import Text.Layout.Table (asciiRoundS, column, def, expandUntil,
rowsG, tableString, titlesH)
data ListOptions = ListOptions
{ ListOptions -> RepoLocationSpec
_listRepoLocation :: RepoLocationSpec
, ListOptions -> ListEntity
_listListEntity :: ListEntity
, ListOptions -> Bool
_listRawOutput :: Bool
, ListOptions -> Bool
_listOnlyLatest :: Bool
}
data RepoLocationSpec = RepoLocal [FilePath] | RepoRemote ArchiveEndpoint
data ListEntity = ListPackages
| ListGroups
| ListIndividuals AddColSpec
| ListBibliography AddColSpec
runList :: ListOptions -> PoseidonIO ()
runList :: ListOptions -> PoseidonIO ()
runList (ListOptions RepoLocationSpec
repoLocation ListEntity
listEntity Bool
rawOutput Bool
onlyLatest) = do
let pacReadOpts :: PackageReadOptions
pacReadOpts = PackageReadOptions
defaultPackageReadOptions {
_readOptIgnoreChecksums = True
, _readOptGenoCheck = False
, _readOptIgnoreGeno = True
, _readOptOnlyLatest = onlyLatest
}
([String]
tableH, [[String]]
tableB) <- case ListEntity
listEntity of
ListEntity
ListPackages -> do
[PackageInfo]
packageInfos <- case RepoLocationSpec
repoLocation of
RepoRemote (ArchiveEndpoint String
remoteURL Maybe String
archive) -> do
String -> PoseidonIO ()
logInfo String
"Downloading package data from server"
ApiReturnData
apiReturn <- String -> Bool -> PoseidonIO ApiReturnData
processApiResponse (String
remoteURL String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/packages" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Maybe String -> String
qDefault Maybe String
archive) Bool
False
case ApiReturnData
apiReturn of
ApiReturnPackageInfo [PackageInfo]
pacInfo -> [PackageInfo] -> ReaderT Env IO [PackageInfo]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [PackageInfo]
pacInfo
ApiReturnData
_ -> String -> ReaderT Env IO [PackageInfo]
forall a. HasCallStack => String -> a
error String
"should not happen"
RepoLocal [String]
baseDirs -> do
[PoseidonPackage]
pacCollection <- PackageReadOptions -> [String] -> PoseidonIO [PoseidonPackage]
readPoseidonPackageCollection PackageReadOptions
pacReadOpts [String]
baseDirs
[PoseidonPackage] -> ReaderT Env IO [PackageInfo]
forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> m [PackageInfo]
packagesToPackageInfos [PoseidonPackage]
pacCollection
let tableH :: [String]
tableH = [String
"Package", String
"Package Version", String
"Is Latest", String
"Poseidon Version", String
"Description", String
"Last modified", String
"Nr Individuals"]
tableB :: [[String]]
tableB = ([String] -> String) -> [[String]] -> [[String]]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn [String] -> String
forall a. HasCallStack => [a] -> a
head ([[String]] -> [[String]]) -> [[String]] -> [[String]]
forall a b. (a -> b) -> a -> b
$ do
pInf :: PackageInfo
pInf@(PackageInfo PacNameAndVersion
_ Bool
isLatest Version
posV Maybe String
desc Maybe Day
lastMod Int
nrInds) <- [PackageInfo]
packageInfos
Bool
True <- Bool -> [Bool]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Bool
not Bool
onlyLatest Bool -> Bool -> Bool
|| Bool
isLatest)
[String] -> [[String]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return [PackageInfo -> String
forall a. HasNameAndVersion a => a -> String
getPacName PackageInfo
pInf, Maybe Version -> String
showMaybeVersion (PackageInfo -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion PackageInfo
pInf), Bool -> String
forall a. Show a => a -> String
show Bool
isLatest,
Version -> String
showVersion Version
posV, Maybe String -> String
showMaybe Maybe String
desc, Maybe String -> String
showMaybe (Day -> String
forall a. Show a => a -> String
show (Day -> String) -> Maybe Day -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Day
lastMod), Int -> String
forall a. Show a => a -> String
show Int
nrInds]
([String], [[String]]) -> ReaderT Env IO ([String], [[String]])
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([String]
tableH, [[String]]
tableB)
ListEntity
ListGroups -> do
[GroupInfo]
groupInfos <- case RepoLocationSpec
repoLocation of
RepoRemote (ArchiveEndpoint String
remoteURL Maybe String
archive) -> do
String -> PoseidonIO ()
logInfo String
"Downloading group data from server"
ApiReturnData
apiReturn <- String -> Bool -> PoseidonIO ApiReturnData
processApiResponse (String
remoteURL String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/groups" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Maybe String -> String
qDefault Maybe String
archive) Bool
False
case ApiReturnData
apiReturn of
ApiReturnGroupInfo [GroupInfo]
groupInfo -> [GroupInfo] -> ReaderT Env IO [GroupInfo]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [GroupInfo]
groupInfo
ApiReturnData
_ -> String -> ReaderT Env IO [GroupInfo]
forall a. HasCallStack => String -> a
error String
"should not happen"
RepoLocal [String]
baseDirs -> do
[PoseidonPackage]
pacCollection <- PackageReadOptions -> [String] -> PoseidonIO [PoseidonPackage]
readPoseidonPackageCollection PackageReadOptions
pacReadOpts [String]
baseDirs
[PoseidonPackage] -> ReaderT Env IO [GroupInfo]
forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> m [GroupInfo]
getAllGroupInfo [PoseidonPackage]
pacCollection
let tableH :: [String]
tableH = [String
"Group", String
"Package", String
"Package Version", String
"Is Latest", String
"Nr Individuals"]
tableB :: [[String]]
tableB = do
gi :: GroupInfo
gi@(GroupInfo String
groupName PacNameAndVersion
_ Bool
isLatest Int
nrInds) <- [GroupInfo]
groupInfos
Bool
True <- Bool -> [Bool]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Bool
not Bool
onlyLatest Bool -> Bool -> Bool
|| Bool
isLatest)
[String] -> [[String]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return [String
groupName, GroupInfo -> String
forall a. HasNameAndVersion a => a -> String
getPacName GroupInfo
gi, Maybe Version -> String
showMaybeVersion (GroupInfo -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion GroupInfo
gi), Bool -> String
forall a. Show a => a -> String
show Bool
isLatest, Int -> String
forall a. Show a => a -> String
show Int
nrInds]
([String], [[String]]) -> ReaderT Env IO ([String], [[String]])
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([String]
tableH, [[String]]
tableB)
ListIndividuals AddColSpec
addJannoColSpec -> do
[ExtendedIndividualInfo]
extIndInfos <- case RepoLocationSpec
repoLocation of
RepoRemote (ArchiveEndpoint String
remoteURL Maybe String
archive) -> do
String -> PoseidonIO ()
logInfo String
"Downloading individual data from server"
let addJannoColFlag :: String
addJannoColFlag = case AddColSpec
addJannoColSpec of
AddColSpec
AddColAll -> String
"&additionalJannoColumns=ALL"
AddColList [] -> String
""
AddColList [String]
moreJannoColumns -> String
"&additionalJannoColumns=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," [String]
moreJannoColumns
ApiReturnData
apiReturn <- String -> Bool -> PoseidonIO ApiReturnData
processApiResponse (String
remoteURL String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/individuals" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Maybe String -> String
qDefault Maybe String
archive String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
addJannoColFlag) Bool
False
case ApiReturnData
apiReturn of
ApiReturnExtIndividualInfo [ExtendedIndividualInfo]
indInfo -> [ExtendedIndividualInfo] -> ReaderT Env IO [ExtendedIndividualInfo]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [ExtendedIndividualInfo]
indInfo
ApiReturnData
_ -> String -> ReaderT Env IO [ExtendedIndividualInfo]
forall a. HasCallStack => String -> a
error String
"should not happen"
RepoLocal [String]
baseDirs -> do
[PoseidonPackage]
pacCollection <- PackageReadOptions -> [String] -> PoseidonIO [PoseidonPackage]
readPoseidonPackageCollection PackageReadOptions
pacReadOpts [String]
baseDirs
[PoseidonPackage]
-> AddColSpec -> ReaderT Env IO [ExtendedIndividualInfo]
forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> AddColSpec -> m [ExtendedIndividualInfo]
getExtendedIndividualInfo [PoseidonPackage]
pacCollection AddColSpec
addJannoColSpec
let addJannoCols :: [String]
addJannoCols = case [ExtendedIndividualInfo]
extIndInfos of
[] -> []
(ExtendedIndividualInfo
e:[ExtendedIndividualInfo]
_) -> ((String, Maybe String) -> String)
-> [(String, Maybe String)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Maybe String) -> String
forall a b. (a, b) -> a
fst ([(String, Maybe String)] -> [String])
-> (ExtendedIndividualInfo -> [(String, Maybe String)])
-> ExtendedIndividualInfo
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedIndividualInfo -> [(String, Maybe String)]
extIndInfoAddCols (ExtendedIndividualInfo -> [String])
-> ExtendedIndividualInfo -> [String]
forall a b. (a -> b) -> a -> b
$ ExtendedIndividualInfo
e
case AddColSpec
addJannoColSpec of
AddColList (String
_:[String]
_) -> do
[(Int, String)]
-> ((Int, String) -> PoseidonIO ()) -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Int] -> [String] -> [(Int, String)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [String]
addJannoCols) (((Int, String) -> PoseidonIO ()) -> PoseidonIO ())
-> ((Int, String) -> PoseidonIO ()) -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ \(Int
i, String
columnKey) -> do
let nonEmptyEntries :: [String]
nonEmptyEntries = [Maybe String] -> [String]
forall a. [Maybe a] -> [a]
catMaybes [(String, Maybe String) -> Maybe String
forall a b. (a, b) -> b
snd ([(String, Maybe String)]
entries [(String, Maybe String)] -> Int -> (String, Maybe String)
forall a. HasCallStack => [a] -> Int -> a
!! Int
i) | ExtendedIndividualInfo String
_ [String]
_ PacNameAndVersion
_ Bool
_ [(String, Maybe String)]
entries <- [ExtendedIndividualInfo]
extIndInfos]
Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
nonEmptyEntries) (PoseidonIO () -> PoseidonIO ())
-> (String -> PoseidonIO ()) -> String -> PoseidonIO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PoseidonIO ()
logWarning (String -> PoseidonIO ()) -> String -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ String
"Column Name " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
columnKey String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" not present in any individual"
AddColSpec
_ -> () -> PoseidonIO ()
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
let tableH :: [String]
tableH = [String
"Individual", String
"Group", String
"Package", String
"PackageVersion", String
"Is Latest"] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
addJannoCols
tableB :: [[String]]
tableB = do
i :: ExtendedIndividualInfo
i@(ExtendedIndividualInfo String
name [String]
groups PacNameAndVersion
_ Bool
isLatest [(String, Maybe String)]
addColumnEntries) <- [ExtendedIndividualInfo]
extIndInfos
Bool
True <- Bool -> [Bool]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Bool
not Bool
onlyLatest Bool -> Bool -> Bool
|| Bool
isLatest)
[String] -> [[String]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> [[String]]) -> [String] -> [[String]]
forall a b. (a -> b) -> a -> b
$ [String
name, String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
groups, ExtendedIndividualInfo -> String
forall a. HasNameAndVersion a => a -> String
getPacName ExtendedIndividualInfo
i,
Maybe Version -> String
showMaybeVersion (ExtendedIndividualInfo -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion ExtendedIndividualInfo
i), Bool -> String
forall a. Show a => a -> String
show Bool
isLatest] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
((String, Maybe String) -> String)
-> [(String, Maybe String)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"n/a" (Maybe String -> String)
-> ((String, Maybe String) -> Maybe String)
-> (String, Maybe String)
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, Maybe String) -> Maybe String
forall a b. (a, b) -> b
snd) [(String, Maybe String)]
addColumnEntries
([String], [[String]]) -> ReaderT Env IO ([String], [[String]])
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([String]
tableH, [[String]]
tableB)
ListBibliography AddColSpec
addColSpec -> do
[BibliographyInfo]
bibInfos <- case RepoLocationSpec
repoLocation of
RepoRemote (ArchiveEndpoint String
remoteURL Maybe String
archive) -> do
String -> PoseidonIO ()
logInfo String
"Downloading bibliography data from server"
let addJannoColFlag :: String
addJannoColFlag = case AddColSpec
addColSpec of
AddColSpec
AddColAll -> String
"&additionalBibColumns=ALL"
AddColList [] -> String
""
AddColList [String]
moreBibFields -> String
"&additionalBibColumns=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," [String]
moreBibFields
ApiReturnData
apiReturn <- String -> Bool -> PoseidonIO ApiReturnData
processApiResponse (String
remoteURL String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/bibliography" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Maybe String -> String
qDefault Maybe String
archive String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
addJannoColFlag) Bool
False
case ApiReturnData
apiReturn of
ApiReturnBibInfo [BibliographyInfo]
bibInfo -> [BibliographyInfo] -> ReaderT Env IO [BibliographyInfo]
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [BibliographyInfo]
bibInfo
ApiReturnData
_ -> String -> ReaderT Env IO [BibliographyInfo]
forall a. HasCallStack => String -> a
error String
"should not happen"
RepoLocal [String]
baseDirs -> do
[PoseidonPackage]
pacCollection <- PackageReadOptions -> [String] -> PoseidonIO [PoseidonPackage]
readPoseidonPackageCollection PackageReadOptions
pacReadOpts [String]
baseDirs
[PoseidonPackage]
-> AddColSpec -> ReaderT Env IO [BibliographyInfo]
forall (m :: * -> *).
MonadThrow m =>
[PoseidonPackage] -> AddColSpec -> m [BibliographyInfo]
getBibliographyInfo [PoseidonPackage]
pacCollection AddColSpec
addColSpec
let addBibFieldNames :: [String]
addBibFieldNames = case AddColSpec
addColSpec of
AddColSpec
AddColAll -> [String] -> [String]
forall a. Eq a => [a] -> [a]
nub ([String] -> [String])
-> ([BibliographyInfo] -> [String])
-> [BibliographyInfo]
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (BibliographyInfo -> [String]) -> [BibliographyInfo] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (((String, Maybe String) -> String)
-> [(String, Maybe String)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Maybe String) -> String
forall a b. (a, b) -> a
fst ([(String, Maybe String)] -> [String])
-> (BibliographyInfo -> [(String, Maybe String)])
-> BibliographyInfo
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BibliographyInfo -> [(String, Maybe String)]
bibInfoAddCols) ([BibliographyInfo] -> [String]) -> [BibliographyInfo] -> [String]
forall a b. (a -> b) -> a -> b
$ [BibliographyInfo]
bibInfos
AddColList [String]
names -> [String]
names
case AddColSpec
addColSpec of
AddColList (String
_:[String]
_) -> do
[String] -> (String -> PoseidonIO ()) -> PoseidonIO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [String]
addBibFieldNames ((String -> PoseidonIO ()) -> PoseidonIO ())
-> (String -> PoseidonIO ()) -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ \String
bibFieldKey -> do
let nonEmptyEntries :: [()]
nonEmptyEntries = do
BibliographyInfo
bibInfo <- [BibliographyInfo]
bibInfos
Just (Just String
_) <- Maybe (Maybe String) -> [Maybe (Maybe String)]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Maybe String) -> [Maybe (Maybe String)])
-> Maybe (Maybe String) -> [Maybe (Maybe String)]
forall a b. (a -> b) -> a -> b
$ String
bibFieldKey String -> [(String, Maybe String)] -> Maybe (Maybe String)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` BibliographyInfo -> [(String, Maybe String)]
bibInfoAddCols BibliographyInfo
bibInfo
() -> [()]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Bool -> PoseidonIO () -> PoseidonIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([()] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [()]
nonEmptyEntries) (PoseidonIO () -> PoseidonIO ())
-> (String -> PoseidonIO ()) -> String -> PoseidonIO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PoseidonIO ()
logWarning (String -> PoseidonIO ()) -> String -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$
String
"Bibliography field " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
bibFieldKey String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"is not present in any bibliography entry"
AddColSpec
_ -> () -> PoseidonIO ()
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
let tableH :: [String]
tableH = [String
"BibKey", String
"Title", String
"Author", String
"Year", String
"DOI",
String
"Nr of samples"] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
addBibFieldNames
tableB :: [[String]]
tableB = do
BibliographyInfo
bibInfo <- [BibliographyInfo]
bibInfos
let addBibFieldColumns :: [String]
addBibFieldColumns = do
String
bibFieldName <- [String]
addBibFieldNames
case String
bibFieldName String -> [(String, Maybe String)] -> Maybe (Maybe String)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` BibliographyInfo -> [(String, Maybe String)]
bibInfoAddCols BibliographyInfo
bibInfo of
Just (Just String
v) -> String -> [String]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return String
v
Maybe (Maybe String)
_ -> String -> [String]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return String
""
[(String, String)]
authors <- String -> [[(String, String)]]
forall (m :: * -> *).
MonadThrow m =>
String -> m [(String, String)]
parseAuthors (String -> [[(String, String)]])
-> (BibliographyInfo -> String)
-> BibliographyInfo
-> [[(String, String)]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe String -> String
curateBibField (Maybe String -> String)
-> (BibliographyInfo -> Maybe String) -> BibliographyInfo -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BibliographyInfo -> Maybe String
bibInfoAuthor (BibliographyInfo -> [[(String, String)]])
-> BibliographyInfo -> [[(String, String)]]
forall a b. (a -> b) -> a -> b
$ BibliographyInfo
bibInfo
[String] -> [[String]]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> [[String]]) -> [String] -> [[String]]
forall a b. (a -> b) -> a -> b
$ [BibliographyInfo -> String
bibInfoKey BibliographyInfo
bibInfo, Maybe String -> String
curateBibField (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ BibliographyInfo -> Maybe String
bibInfoTitle BibliographyInfo
bibInfo, [(String, String)] -> String
authorAbbrvString [(String, String)]
authors,
Maybe String -> String
curateBibField (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ BibliographyInfo -> Maybe String
bibInfoYear BibliographyInfo
bibInfo,
Maybe String -> String
curateBibField (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ BibliographyInfo -> Maybe String
bibInfoDoi BibliographyInfo
bibInfo, Int -> String
forall a. Show a => a -> String
show (BibliographyInfo -> Int
bibInfoNrSamples BibliographyInfo
bibInfo)] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
[String]
addBibFieldColumns
([String], [[String]]) -> ReaderT Env IO ([String], [[String]])
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([String]
tableH, [[String]]
tableB)
if Bool
rawOutput then
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" [String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\t" [String]
row | [String]
row <- [String]
tableH[String] -> [[String]] -> [[String]]
forall a. a -> [a] -> [a]
:[[String]]
tableB]
else do
let colSpecs :: [ColSpec]
colSpecs = Int -> ColSpec -> [ColSpec]
forall a. Int -> a -> [a]
replicate ([String] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
tableH) (LenSpec -> Position H -> AlignSpec -> CutMark -> ColSpec
column (Int -> LenSpec
expandUntil Int
60) Position H
forall a. Default a => a
def AlignSpec
forall a. Default a => a
def CutMark
forall a. Default a => a
def)
IO () -> PoseidonIO ()
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> PoseidonIO ()) -> IO () -> PoseidonIO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [ColSpec]
-> TableStyle -> HeaderSpec -> [RowGroup String] -> String
forall a.
Cell a =>
[ColSpec] -> TableStyle -> HeaderSpec -> [RowGroup a] -> String
tableString [ColSpec]
colSpecs TableStyle
asciiRoundS ([String] -> HeaderSpec
titlesH [String]
tableH) [[[String]] -> RowGroup String
forall a. [Row a] -> RowGroup a
rowsG [[String]]
tableB]
where
showMaybe :: Maybe String -> String
showMaybe :: Maybe String -> String
showMaybe = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"n/a"
showMaybeVersion :: Maybe Version -> String
showMaybeVersion :: Maybe Version -> String
showMaybeVersion = String -> (Version -> String) -> Maybe Version -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"n/a" Version -> String
showVersion
curateBibField :: Maybe String -> String
curateBibField :: Maybe String -> String
curateBibField = Text -> String
T.unpack (Text -> String)
-> (Maybe String -> Text) -> Maybe String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text] -> Text
T.intercalate Text
" " ([Text] -> Text)
-> (Maybe String -> [Text]) -> Maybe String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
T.strip ([Text] -> [Text])
-> (Maybe String -> [Text]) -> Maybe String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
T.lines (Text -> [Text])
-> (Maybe String -> Text) -> Maybe String -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text)
-> (Maybe String -> String) -> Maybe String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
""