{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

-- | Copyright: (c) 2020 berberman
-- SPDX-License-Identifier: MIT
-- Maintainer: berberman <1793913507@qq.com>
-- Stability: experimental
-- Portability: portable
-- This module provides simple pretty-printing functions work with the cli program.
module Distribution.ArchHs.PP
  ( prettySkip,
    prettyFlagAssignments,
    prettyFlags,
    prettySolvedPkgs,
    prettyDeps,
  )
where

import qualified Colourista as C
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import Distribution.ArchHs.Internal.Prelude
import Distribution.ArchHs.Types

prettySkip :: [String] -> String
prettySkip :: [String] -> String
prettySkip = [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.magenta] (String -> String) -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", "

prettyFlagAssignments :: Map.Map PackageName FlagAssignment -> String
prettyFlagAssignments :: Map PackageName FlagAssignment -> String
prettyFlagAssignments Map PackageName FlagAssignment
m =
  [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
    ([(PackageName, FlagAssignment)] -> [String])
-> (Map PackageName FlagAssignment
    -> [(PackageName, FlagAssignment)])
-> Map PackageName FlagAssignment
-> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((PackageName, FlagAssignment) -> String)
-> [(PackageName, FlagAssignment)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(PackageName
n, FlagAssignment
a) -> [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.magenta] (PackageName -> String
unPackageName PackageName
n) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> FlagAssignment -> String
prettyFlagAssignment FlagAssignment
a)) Map PackageName FlagAssignment -> [(PackageName, FlagAssignment)]
forall k a. Map k a -> [(k, a)]
Map.toList Map PackageName FlagAssignment
m

prettyFlagAssignment :: FlagAssignment -> String
prettyFlagAssignment :: FlagAssignment -> String
prettyFlagAssignment FlagAssignment
m =
  [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
    (\(FlagName
n, Bool
v) -> String
"    ⚐ " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.yellow] (FlagName -> String
unFlagName FlagName
n) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" : " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.cyan] (Bool -> String
forall a. Show a => a -> String
show Bool
v) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n") ((FlagName, Bool) -> String) -> [(FlagName, Bool)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FlagAssignment -> [(FlagName, Bool)]
unFlagAssignment FlagAssignment
m

prettyDeps :: [PackageName] -> String
prettyDeps :: [PackageName] -> String
prettyDeps =
  [String] -> String
forall a. Monoid a => [a] -> a
mconcat
    ([String] -> String)
-> ([PackageName] -> [String]) -> [PackageName] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, PackageName) -> String) -> [(Int, PackageName)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Int
i, PackageName
n) -> Int -> String
forall a. Show a => a -> String
show (Int
i :: Int) String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
". " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PackageName -> String
unPackageName PackageName
n String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n")
    ([(Int, PackageName)] -> [String])
-> ([PackageName] -> [(Int, PackageName)])
-> [PackageName]
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [PackageName] -> [(Int, PackageName)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1 ..]

prettyFlags :: [(PackageName, [Flag])] -> String
prettyFlags :: [(PackageName, [Flag])] -> String
prettyFlags = [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String)
-> ([(PackageName, [Flag])] -> [String])
-> [(PackageName, [Flag])]
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((PackageName, [Flag]) -> String)
-> [(PackageName, [Flag])] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(PackageName
name, [Flag]
flags) -> [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.magenta] (PackageName -> String
unPackageName PackageName
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n") String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [Int -> String
forall str. (IsString str, Semigroup str) => Int -> str
C.indent Int
4] (String -> String) -> (Flag -> String) -> Flag -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Flag -> String
prettyFlag (Flag -> String) -> [Flag] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Flag]
flags))

prettyFlag :: Flag -> String
prettyFlag :: Flag -> String
prettyFlag Flag
f = String
"⚐ " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.yellow] String
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
":\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [String] -> String
forall a. Monoid a => [a] -> a
mconcat ([String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [Int -> String
forall str. (IsString str, Semigroup str) => Int -> str
C.indent Int
6] (String -> String) -> [String] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String
"description:\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
desc, String
"default: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
def String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n", String
"isManual: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
manual String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n"])
  where
    name :: String
name = FlagName -> String
unFlagName (FlagName -> String) -> (Flag -> FlagName) -> Flag -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Flag -> FlagName
flagName (Flag -> String) -> Flag -> String
forall a b. (a -> b) -> a -> b
$ Flag
f
    desc :: String
desc = [String] -> String
unlines ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String) -> [String] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [Int -> String
forall str. (IsString str, Semigroup str) => Int -> str
C.indent Int
8]) ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Flag -> String
flagDescription Flag
f
    def :: String
def = Bool -> String
forall a. Show a => a -> String
show (Bool -> String) -> Bool -> String
forall a b. (a -> b) -> a -> b
$ Flag -> Bool
flagDefault Flag
f
    manual :: String
manual = Bool -> String
forall a. Show a => a -> String
show (Bool -> String) -> Bool -> String
forall a b. (a -> b) -> a -> b
$ Flag -> Bool
flagManual Flag
f

prettySolvedPkgs :: [SolvedPackage] -> String
prettySolvedPkgs :: [SolvedPackage] -> String
prettySolvedPkgs = [(String, String)] -> String
con ([(String, String)] -> String)
-> ([SolvedPackage] -> [(String, String)])
-> [SolvedPackage]
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[(String, String)]] -> [(String, String)]
forall a. Monoid a => [a] -> a
mconcat ([[(String, String)]] -> [(String, String)])
-> ([SolvedPackage] -> [[(String, String)]])
-> [SolvedPackage]
-> [(String, String)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SolvedPackage -> [(String, String)])
-> [SolvedPackage] -> [[(String, String)]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SolvedPackage -> [(String, String)]
prettySolvedPkg

prettySolvedPkg :: SolvedPackage -> [(String, String)]
prettySolvedPkg :: SolvedPackage -> [(String, String)]
prettySolvedPkg SolvedPackage {[SolvedDependency]
PackageName
_pkgDeps :: SolvedPackage -> [SolvedDependency]
_pkgName :: SolvedPackage -> PackageName
_pkgDeps :: [SolvedDependency]
_pkgName :: PackageName
..} =
  ([String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.bold, String
forall str. IsString str => str
C.yellow] (PackageName -> String
unPackageName PackageName
_pkgName), [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.red] String
"    ✘") (String, String) -> [(String, String)] -> [(String, String)]
forall a. a -> [a] -> [a]
:
  ((Int, SolvedDependency) -> (String, String))
-> [(Int, SolvedDependency)] -> [(String, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
    ( \(Int
i :: Int, SolvedDependency {[DependencyType]
Maybe DependencyProvider
PackageName
_depType :: SolvedDependency -> [DependencyType]
_depName :: SolvedDependency -> PackageName
_depProvider :: SolvedDependency -> Maybe DependencyProvider
_depType :: [DependencyType]
_depName :: PackageName
_depProvider :: Maybe DependencyProvider
..}) ->
        let prefix :: Text
prefix = if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [SolvedDependency] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SolvedDependency]
_pkgDeps then Text
" └─" else Text
" ├─"
         in case Maybe DependencyProvider
_depProvider of
              (Just DependencyProvider
x) -> ([String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.green] (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
prefix String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PackageName -> String
unPackageName PackageName
_depName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [DependencyType] -> String
forall a. Show a => a -> String
show [DependencyType]
_depType, [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.green] String
"✔ " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.cyan] (DependencyProvider -> String
forall a. Show a => a -> String
show DependencyProvider
x))
              Maybe DependencyProvider
_ -> ([String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.bold, String
forall str. IsString str => str
C.yellow] (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
prefix String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PackageName -> String
unPackageName PackageName
_depName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [DependencyType] -> String
forall a. Show a => a -> String
show [DependencyType]
_depType, [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.red] String
"    ✘")
    )
    ([Int] -> [SolvedDependency] -> [(Int, SolvedDependency)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1 ..] [SolvedDependency]
_pkgDeps)
prettySolvedPkg ProvidedPackage {PackageName
DependencyProvider
_pkgProvider :: SolvedPackage -> DependencyProvider
_pkgProvider :: DependencyProvider
_pkgName :: PackageName
_pkgName :: SolvedPackage -> PackageName
..} = [([String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.green] (PackageName -> String
unPackageName PackageName
_pkgName), [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.green] String
"✔ " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [String] -> String -> String
forall str. (IsString str, Semigroup str) => [str] -> str -> str
C.formatWith [String
forall str. IsString str => str
C.cyan] (DependencyProvider -> String
forall a. Show a => a -> String
show DependencyProvider
_pkgProvider))]

con :: [(String, String)] -> String
con :: [(String, String)] -> String
con [(String, String)]
l = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String]
complemented
  where
    maxL :: Int
maxL = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ ((String, String) -> Int) -> [(String, String)] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String -> Int)
-> ((String, String) -> String) -> (String, String) -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, String) -> String
forall a b. (a, b) -> a
fst) [(String, String)]
l
    complemented :: [String]
complemented = (\(String
x, String
y) -> String
x String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
maxL Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
x) Char
' ' String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
y String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n") ((String, String) -> String) -> [(String, String)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(String, String)]
l