{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE OverloadedStrings #-} module Data.VRML.Text where import Data.VRML.Types import GHC.Generics import Data.Int import Data.Void import Control.Monad (void) import Data.Char (isSpace) import Data.Text hiding (empty, foldl, map) import qualified Data.Text.Lazy.IO as TL import Text.Megaparsec import Text.Megaparsec.Char as C import Text.Megaparsec.Char.Lexer as L import Data.Text.Prettyprint.Doc import Data.Text.Prettyprint.Doc.Render.Text indent' = indent 2 instance Pretty VRML where pretty (VRML version statements) = header <> vsep (map pretty statements) <> line where header = "#" <> pretty version <> line instance Pretty Statement where pretty (StNode v) = pretty v pretty (StProto v) = pretty v pretty (StRoute v) = pretty v instance Pretty NodeStatement where pretty (DEF nodeNameId node) = "DEF" <+> pretty nodeNameId <+> pretty node pretty (USE nodeNameId) = "USE" <+> pretty nodeNameId pretty (NodeStatement node) = pretty node instance Pretty ProtoStatement where pretty (Proto nodeTypeId interfaces ps node st) = vsep [ "PROTO" <+> pretty nodeTypeId <+> "[" , indent' (vsep (map pretty interfaces)) , "]" , "{" , indent' (vsep ( (map (\v -> pretty v <> line ) ps) ++ [pretty node] ++ (map (\v -> pretty v <> line ) st) )) , "}" ] pretty (ExternProto nodeTypeId interfaces urllist) = vsep [ "EXTERNPROTO" <+> pretty nodeTypeId <+> "[" , indent' (vsep (map pretty interfaces)) , "]" , pretty urllist ] instance Pretty RestrictedInterface where pretty (RestrictedInterfaceEventIn ft ei) = "eventIn" <+> pretty ft <+> pretty ei pretty (RestrictedInterfaceEventOut ft eo) = "eventOut" <+> pretty ft <+> pretty eo pretty (RestrictedInterfaceField ft fi fv) = "field" <+> pretty ft <+> pretty fi <+> pretty fv instance Pretty Interface where pretty (InterfaceEventIn ft ei) = "eventIn" <+> pretty ft <+> pretty ei pretty (InterfaceEventOut ft eo) = "eventOut" <+> pretty ft <+> pretty eo pretty (InterfaceField ft fi fv) = "field" <+> pretty ft <+> pretty fi <+> pretty fv pretty (InterfaceExposedField ft fi fv) = "exposedField" <+> pretty ft <+> pretty fi <+> pretty fv instance Pretty ExternInterface where pretty (ExternInterfaceEventIn ft ei) = "eventIn" <+> pretty ft <+> pretty ei pretty (ExternInterfaceEventOut ft eo) = "eventOut" <+> pretty ft <+> pretty eo pretty (ExternInterfaceField ft fi) = "field" <+> pretty ft <+> pretty fi pretty (ExternInterfaceExposedField ft fi) = "exposedField" <+> pretty ft <+> pretty fi instance Pretty Route where pretty (Route nidOut eo nidIn ei) = "ROUTE" <+> pretty nidOut <> "." <> pretty eo <+> pretty nidIn <> "." <> pretty ei instance Pretty URLList where pretty (URLList urls) = vsep [ "[" , indent' (vsep (map (\url -> pretty (Sstring url) <> line) urls)) , "]" ] instance Pretty Node where pretty (Node ntypeid bodys) = vsep [ pretty ntypeid <+> "{" , indent' (vsep (map (\v -> pretty v) bodys)) , "}" ] pretty (Script bodys) = vsep [ "Script" <+> "{" , indent' (vsep (map (\v -> pretty v) bodys)) , "}" ] instance Pretty ScriptBodyElement where pretty (SBNode v) = pretty v pretty (SBRestrictedInterface v) = pretty v pretty (SBEventIn etype eid1 eid2) = "eventIn" <+> pretty etype <+> pretty eid1 <+> "IS" <+>pretty eid2 pretty (SBEventOut etype eid1 eid2) = "eventOut" <+> pretty etype <+> pretty eid1 <+> "IS" <+>pretty eid2 pretty (SBFieldId etype eid1 eid2) = "field" <+> pretty etype <+> pretty eid1 <+> "IS" <+>pretty eid2 instance Pretty NodeBodyElement where pretty (FV fid fv) = pretty fid <+> pretty fv pretty (NBFieldId fid1 fid2) = pretty fid1 <+> pretty fid2 pretty (NBEventIn eid1 eid2) = pretty eid1 <+> "IS" <+>pretty eid2 pretty (NBEventOut eid1 eid2) = pretty eid1 <+> "IS" <+>pretty eid2 pretty (NBRoute r) = pretty r pretty (NBProto p) = pretty p instance Pretty NodeNameId where pretty (NodeNameId str) = pretty str instance Pretty NodeTypeId where pretty (NodeTypeId str) = pretty str instance Pretty FieldId where pretty (FieldId str) = pretty str instance Pretty EventInId where pretty (EventInId str) = pretty str instance Pretty EventOutId where pretty (EventOutId str) = pretty str instance Pretty FieldType where pretty MFBool = "MFBool" pretty MFColor = "MFColor" pretty MFFloat = "MFFloat" pretty MFString = "MFString" pretty MFTime = "MFTime" pretty MFVec2f = "MFVec2f" pretty MFVec3f = "MFVec3f" pretty SFBool = "SFBool" pretty SFColor = "SFColor" pretty SFFloat = "SFFloat" pretty SFImage = "SFImage" pretty SFInt32 = "SFInt32" pretty SFNode = "SFNode" pretty SFRotation = "SFRotation" pretty SFString = "SFString" pretty SFTime = "SFTime" pretty SFVec2f = "SFVec2f" pretty SFVec3f = "SFVec3f" instance Pretty FieldValue where pretty (Sbool True) = "TRUE" pretty (Sbool False) = "FALSE" pretty (Scolor (Color (v1,v2,v3))) = pretty v1 <+> pretty v2 <+> pretty v3 pretty (Sfloat v) = pretty v pretty (Simage v) = foldl (<+>) "[" (map pretty v) <+> "]" pretty (Sint32 v) = pretty v pretty (Snode (Just v)) = pretty v pretty (Snode Nothing) = "NULL" pretty (Srotation (v1,v2,v3,v4)) = pretty v1 <+> pretty v2 <+> pretty v3 <+> pretty v4 pretty (Sstring v) = let rep [] = [] rep ('"' : xs) = '\\' : '"' : rep xs rep (x : xs) = x : rep xs in "\"" <> pretty(rep v) <> "\"" pretty (Stime (Time v)) = pretty v pretty (Svec2f (v1,v2)) = pretty v1 <+> pretty v2 pretty (Svec3f (v1,v2,v3)) = pretty v1 <+> pretty v2 <+> pretty v3 pretty (Mbool vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Sbool v)) vs)) , "]" ] pretty (Mcolor vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Scolor v)) vs)) , "]" ] pretty (Mfloat vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Sfloat v)) vs)) , "]" ] pretty (Mint32 vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Sint32 v)) vs)) , "]" ] pretty (Mnode vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Snode (Just v))) vs)) , "]" ] pretty (Mrotation vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Srotation v)) vs)) , "]" ] pretty (Mstring vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Sstring v)) vs)) , "]" ] pretty (Mtime vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Stime v)) vs)) , "]" ] pretty (Mvec2f vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Svec2f v)) vs)) , "]" ] pretty (Mvec3f vs) = vsep [ "[" , indent' (vsep (map (\v -> pretty (Svec3f v)) vs)) , "]" ] writeVRML :: FilePath -> VRML -> IO () writeVRML filename doc = TL.writeFile filename $ renderLazy $ layoutPretty defaultLayoutOptions (pretty doc)