packages feed

descript-lang-0.2.0.0: src/Descript/Misc/Build/Write/Compile/Package.hs

{-# LANGUAGE OverloadedStrings #-}

module Descript.Misc.Build.Write.Compile.Package
  ( PackageContents (..)
  , Package (..)
  , savePackage
  , pprintPackage
  ) where

import Descript.Misc.Summary
import Data.Monoid
import Data.ByteString (ByteString)
import qualified Data.ByteString as ByteString
import System.FilePath
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Core.Data.Text as Text
import qualified Data.Text.Encoding as Text

data PackageContents
  = PackageFile ByteString
  | PackageDirectory [Package]
  deriving (Eq, Ord, Read, Show)

-- | The final output of a compile. Can be a single file or a directory
-- of sub-packages.
data Package
  = Package
  { packageName :: String -- ^ Name of file (with extension) or directory.
  , packageContents :: PackageContents
  } deriving (Eq, Ord, Read, Show)

instance Summary Package where
  summary = Text.unpack . pprintPackage

-- | Writes the package to the given path.
savePackage :: FilePath -> Package -> IO ()
savePackage dir (Package name contents)
  = savePackageContents (dir </> name) contents

savePackageContents :: FilePath -> PackageContents -> IO ()
savePackageContents path (PackageFile content) = ByteString.writeFile path content
savePackageContents path (PackageDirectory subs) = mapM_ (savePackage path) subs

-- | Pretty-prints the package. Files which aren't text (e.g. images)
-- won't print well, however.
pprintPackage :: Package -> Text
pprintPackage (Package name contents)
  = Text.pack name <> "\n" <> pprintPackageContents contents

pprintPackageContents :: PackageContents -> Text
pprintPackageContents (PackageFile content) = indentContent $ Text.decodeUtf8 content
pprintPackageContents (PackageDirectory subs)
  = Text.unlines $ map (indentSubPackage . pprintPackage) subs

indentSubPackage :: Text -> Text
indentSubPackage = Text.indentBullet

indentContent :: Text -> Text
indentContent = Text.indentBlockQuote