{-# LANGUAGE LambdaCase #-} module Nix.XML where import Data.Fix import qualified Data.HashMap.Lazy as M import Data.List import Data.Ord import qualified Data.Text as Text import Nix.Atoms import Nix.Expr.Types import Nix.Value import Text.XML.Light toXML :: Functor m => NValueNF m -> String toXML = (.) ((++ "\n") . ("<?xml version='1.0' encoding='utf-8'?>\n" ++) . ppElement . (\e -> Element (unqual "expr") [] [Elem e] Nothing)) $ cata $ \case NVConstantF a -> case a of NInt n -> mkElem "int" "value" (show n) NFloat f -> mkElem "float" "value" (show f) NBool b -> mkElem "bool" "value" (if b then "true" else "false") NNull -> Element (unqual "null") [] [] Nothing NVStrF t _ -> mkElem "string" "value" (Text.unpack t) NVListF l -> Element (unqual "list") [] (Elem <$> l) Nothing NVSetF s _ -> Element (unqual "attrs") [] (map (\(k, v) -> Elem (Element (unqual "attr") [Attr (unqual "name") (Text.unpack k)] [Elem v] Nothing)) (sortBy (comparing fst) $ M.toList s)) Nothing NVClosureF p _ -> Element (unqual "function") [] (paramsXML p) Nothing NVPathF fp -> mkElem "path" "value" fp NVBuiltinF name _ -> mkElem "function" "name" name mkElem :: String -> String -> String -> Element mkElem n a v = Element (unqual n) [Attr (unqual a) v] [] Nothing paramsXML :: Params r -> [Content] paramsXML (Param name) = [Elem $ mkElem "varpat" "name" (Text.unpack name)] paramsXML (ParamSet s b mname) = [Elem $ Element (unqual "attrspat") (battr ++ nattr) (paramSetXML s) Nothing] where battr = [ Attr (unqual "ellipsis") "1" | b ] nattr = maybe [] ((:[]) . Attr (unqual "name") . Text.unpack) mname paramSetXML :: ParamSet r -> [Content] paramSetXML = map (\(k,_) -> Elem $ mkElem "attr" "name" (Text.unpack k))