{-# LANGUAGE OverloadedStrings #-}

module Hie.Yaml
  ( hieYaml,
    fmtComponent,
    fmtPkgs,
    cabalComponent,
    stackComponent,
  )
where

import qualified Data.Text as T
import Hie.Cabal.Parser

hieYaml :: String -> String -> String
hieYaml :: String -> String -> String
hieYaml String
sOrC String
pkgs =
  String
"cradle:\n"
    String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
indent'
      (String
sOrC String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
":\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
indent' String
pkgs)

indent' :: String -> String
indent' :: String -> String
indent' =
  [String] -> String
unlines
    ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map
      ( \String
l -> case String
l of
          String
"" -> String
""
          String
_ -> String
"  " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
l
      )
    ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines

cabalComponent :: Name -> Component -> (FilePath, String)
cabalComponent :: Name -> Component -> (String, String)
cabalComponent Name
n (Comp CompType
Lib Name
"" Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
"lib:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
n)
cabalComponent Name
n (Comp CompType
Lib Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":lib:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)
cabalComponent Name
n (Comp CompType
Exe Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":exe:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)
cabalComponent Name
n (Comp CompType
Bench Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":bench:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)
cabalComponent Name
n (Comp CompType
Test Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":test:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)

stackComponent :: Name -> Component -> (FilePath, String)
stackComponent :: Name -> Component -> (String, String)
stackComponent Name
n (Comp CompType
Lib Name
"" Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":lib")
stackComponent Name
n (Comp CompType
Lib Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":lib:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)
stackComponent Name
n (Comp CompType
Exe Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":exe:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)
stackComponent Name
n (Comp CompType
Bench Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":bench:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)
stackComponent Name
n (Comp CompType
Test Name
cn Name
p) = (Name -> String
T.unpack Name
p, Name -> String
T.unpack (Name -> String) -> Name -> String
forall a b. (a -> b) -> a -> b
$ Name
n Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
":test:" Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
cn)

fmtComponent :: (FilePath, String) -> String
fmtComponent :: (String, String) -> String
fmtComponent (String
p, String
c) =
  String
"- path: "
    String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
dQuote String
p
    String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n  "
    String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"component: "
    String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
dQuote String
c

-- | Same as init but handle empty list without throwing errors.
dropLast :: [a] -> [a]
dropLast :: [a] -> [a]
dropLast [a]
l = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [a]
l

fmtPkgs :: String -> [Package] -> String
fmtPkgs :: String -> [Package] -> String
fmtPkgs String
sOrC [Package]
pkgs = String -> String
forall a. [a] -> [a]
dropLast (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [String]
l
  where
    comp :: Name -> Component -> (String, String)
comp = if String
sOrC String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"cabal" then Name -> Component -> (String, String)
cabalComponent else Name -> Component -> (String, String)
stackComponent
    f :: Package -> [String]
f (Package Name
n [Component]
cs) = (Component -> String) -> [Component] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n") (String -> String) -> (Component -> String) -> Component -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, String) -> String
fmtComponent ((String, String) -> String)
-> (Component -> (String, String)) -> Component -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Component -> (String, String)
comp Name
n) [Component]
cs
    l :: [String]
l = (Package -> [String]) -> [Package] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Package -> [String]
f [Package]
pkgs

dQuote :: String -> String
dQuote :: String -> String
dQuote String
t = Char
'"' Char -> String -> String
forall a. a -> [a] -> [a]
: String
t String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\""