packages feed

exherbo-cabal-0.2.1.1: src/ExRender/Base.hs

-- Copyright © 2015 Mykola Orliuk <virkony@gmail.com>
-- Distributed under the terms of the GNU General Public License v2

{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE FlexibleInstances #-}

module ExRender.Base
    ( module ExRender.Base
    , module Text.PrettyPrint
    ) where

import Text.PrettyPrint

-- | Wrap width soft limit
exWrapWidth ∷ Int
exWrapWidth = 100

class ExRender a where
    -- | Renders 'a' into a 'Doc' representing some part of exheres
    exDisp ∷ a → Doc

class ExRenderQ a where
    -- | Renders 'a' into a 'Doc' to be placed within double-quotes inside of exheres
    exDispQ ∷ a → Doc

-- | Double-quoted string for bash
dquoted ∷ String → String
dquoted [] = []
dquoted ('\\':xs) = "\\\\" ++ dquoted xs
dquoted ('"':xs) = "\\\"" ++ dquoted xs
dquoted ('`':xs) = "\\`" ++ dquoted xs
dquoted ('$':xs) = "\\$" ++ dquoted xs
dquoted (x:xs) = x : dquoted xs

-- | Split String in lines according to soft limit
softWidth ∷ Int → [String] → [[String]]
softWidth width = build 0 [] where
    build _ ys [] = [reverse ys]
    build 0 [] (w:ws) = build (length w) [w] ws
    build n ys (w:ws) | n' > width = reverse ys : build 0 [] (w:ws)
                      | otherwise = build n' (w : ys) ws
        where
            n' = length w + n

-- | Build a Doc out of String respecting soft width limit
reflow ∷ Int → String → Doc
reflow width = vcat . map (text . unwords) . softWidth width . words

-- | Wrap doc with spaces around if non-empty
spaces ∷ Doc → Doc
spaces doc | isEmpty doc = empty
           | otherwise = space <> doc <> space

-- | Wrap with brackets non-empty doc
nbrackets ∷ Doc → Doc
nbrackets doc | isEmpty doc = empty
              | otherwise = brackets doc

-- | Render a multi-line meta-field of Exheres if non-empty value
exFieldDoc ∷ String → Doc → Doc
exFieldDoc name value | isEmpty value = empty
                      | otherwise = vcat [text name <> text "=\"", value, char '"']

-- |Render a single-line with potential wrap meta-field of Exheres if non-empty value
exField ∷ String → String → Doc
exField _ "" = empty
exField name x | length singleLine <= exWrapWidth = text singleLine
               | otherwise = exFieldDoc name (reflow exWrapWidth (dquoted x))
    where
        singleLine = name ++ "=\"" ++ dquoted x ++ "\""

instance ExRenderQ String where
    -- TODO: exDispQ = sep . map text . words . dquoted
    exDispQ = text . dquoted