{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.GCode.Pretty(
ppGCode
, ppGCodeLine
, ppGCodeCompact
, ppGCodeLineCompact
, ppGCodeStyle
, ppGCodeLineStyle
, ppAxes
, ppAxesMap
) where
import Data.Map (Map)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8
import qualified Data.Double.Conversion.Text
import qualified Data.Map
import qualified Data.Text
import Data.GCode.Types
import Text.PrettyPrint.ANSI.Leijen
ppGCode :: GCode -> String
ppGCode = ppGCodeStyle (defaultStyle { styleColorful = True })
ppGCodeLine :: Code -> String
ppGCodeLine = ppGCodeLineStyle (defaultStyle { styleColorful = True })
ppGCodeCompact :: GCode -> String
ppGCodeCompact = ppGCodeStyle defaultStyle
ppGCodeLineCompact :: Code -> String
ppGCodeLineCompact = ppGCodeLineStyle defaultStyle
ppGCodeStyle :: Style -> GCode -> String
ppGCodeStyle style res = displayS ((renderer style) (ppGCode' style res)) ""
where renderer style' | styleColorful style' == True = renderPretty 0.4 80
renderer _ = renderCompact
ppGCodeLineStyle :: Style -> Code -> String
ppGCodeLineStyle style res = displayS ((renderer style) (ppCode style res)) ""
where renderer style' | styleColorful style' == True = renderPretty 0.4 80
renderer _ = renderCompact
ppList :: (a -> Doc) -> [a] -> Doc
ppList pp x = hsep $ map pp x
ppGCode' :: Style -> [Code] -> Doc
ppGCode' style code = (vsep $ map (ppCode style) code) <> hardline
ppMaybe :: (t -> Doc) -> Maybe t -> Doc
ppMaybe pp (Just x) = pp x
ppMaybe _ Nothing = empty
ppMaybeClass :: Maybe Class -> Doc
ppMaybeClass = ppMaybe ppClass
ppClass :: Class -> Doc
ppClass G = yellow $ text "G"
ppClass M = red $ text "M"
ppClass T = magenta $ text "T"
ppClass PStandalone = red $ text "P"
ppClass FStandalone = red $ text "F"
ppClass SStandalone = red $ text "S"
ccMaybes :: (Eq a, Num a) => Maybe Class -> Maybe a -> Doc -> Doc
ccMaybes (Just cls') (Just num') = cc cls' num'
ccMaybes _ _ = id
cc :: (Eq a, Num a) => Class -> a -> Doc -> Doc
cc G 0 = dullyellow
cc G 1 = yellow
cc _ _ = red
ppAxis :: Style -> (AxisDesignator, Double) -> Doc
ppAxis style (des, val) =
bold (axisColor des $ text $ show des)
<> cyan (
text
$ Data.Text.unpack
$ Data.Double.Conversion.Text.toFixed (stylePrecision style) val
)
axisColor :: AxisDesignator -> Doc -> Doc
axisColor X = red
axisColor Y = green
axisColor Z = yellow
axisColor A = red
axisColor B = green
axisColor C = blue
axisColor E = magenta
axisColor _ = id
ppAxes :: Style -> [(AxisDesignator, Double)] -> Doc
ppAxes style x = ppList (ppAxis style) x
ppAxesMap :: Style -> Map AxisDesignator Double -> Doc
ppAxesMap style x = ppList (ppAxis style) (Data.Map.toList x)
ppParam :: Show a => Style -> (a, Double) -> Doc
ppParam style (des, val) =
bold (blue $ text $ show des)
<> white (
text
$ Data.Text.unpack
$ Data.Double.Conversion.Text.toFixed (stylePrecision style) val
)
ppParams :: Show a => Style -> [(a, Double)] -> Doc
ppParams _ [] = empty
ppParams style x = space <> ppList (ppParam style) x
ppComment :: ByteString -> Doc
ppComment "" = empty
ppComment c = space <> ppComment' c
ppComment' :: ByteString -> Doc
ppComment' "" = empty
ppComment' c = dullwhite $ parens $ text $ Data.ByteString.Char8.unpack c
ppCode :: Style -> Code -> Doc
ppCode style Code{..} =
ccMaybes codeCls codeNum ( bold $ ppMaybeClass codeCls)
<> ccMaybes codeCls codeNum ( ppMaybe (text . show) codeNum)
<> ppMaybe (\x -> (text ".") <> (text $ show x)) codeSub
<> ifNonEmpty (\x -> space <> ppAxesMap style x) codeAxes
<> ppParams style (Data.Map.toList codeParams)
<> ppComment codeComment
ppCode _ (Comment x) = ppComment' x
ppCode _ (Other x) = dullred $ text $ Data.ByteString.Char8.unpack x
ppCode _ (Empty) = empty
{-# INLINE ppCode #-}
ifNonEmpty :: (Eq t, Monoid t)
=> (t -> Doc)
-> t -> Doc
ifNonEmpty _ x | x == mempty = empty
ifNonEmpty f x | otherwise = f x