json2nix: use nixfmt internally

This helps with creating better error messages,
because we can now see where in the pipeline
the error occurred
This commit is contained in:
Oystein Kristoffer Tveit 2022-11-26 20:50:22 +01:00
parent eab555988e
commit fa2f0fd6b4
Signed by: oysteikt
GPG Key ID: 9F2F7D8250F35146
4 changed files with 52 additions and 31 deletions

View File

@ -1,4 +1,7 @@
{ pkgs, ... }:
pkgs.writers.writeHaskellBin "json2nix" {
libraries = with pkgs.haskellPackages; [ aeson ];
let
overlayedPkgs = pkgs.extend
(pkgs.callPackage ./haskell-overlay.nix { compiler = "ghc942"; });
in overlayedPkgs.writers.writeHaskellBin "json2nix" {
libraries = with overlayedPkgs.haskellPackages; [ aeson nixfmt extra text ];
} (builtins.readFile ./json2nix.hs)

View File

@ -0,0 +1,10 @@
{ pkgs, compiler, ... }:
final: prev: {
haskellPackages = with prev.haskell.lib;
prev.haskell.packages.${compiler}.override {
overrides = hpFinal: hpPrev: {
# Upgrade nixfmts "text" dependency to >= 2
nixfmt = doJailbreak hpPrev.nixfmt;
};
};
}

View File

@ -1,35 +1,43 @@
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson (Value(..), decode)
import Data.Aeson.Key (Key, toString)
import Data.Aeson.KeyMap (foldMapWithKey)
import Data.Aeson.Parser (json')
import Data.Aeson.Types (parse)
import Data.String (fromString)
import Data.Text (Text(..), unpack, replace, isInfixOf)
import Data.Vector (Vector)
import Data.Maybe (fromMaybe)
import qualified Data.Aeson as A
import qualified Data.Aeson.Key as A
import qualified Data.Aeson.KeyMap as A
import qualified Data.ByteString as BS
import qualified Data.Either.Extra as E
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Vector as V
import Nixfmt (format)
main :: IO ()
main = interact f
main = BS.interact parseNixCode
parseNixCode :: BS.ByteString -> BS.ByteString
parseNixCode input = T.encodeUtf8 $ E.fromEither formattedNixCode
where
f input = case decode $ fromString input of
Nothing -> "json2nix error - could not parse input\n" ++ show input
Just jsonValue -> json2Nix jsonValue
addErrPrefix :: T.Text -> Either String a -> Either T.Text a
addErrPrefix prefix = E.mapLeft (T.append prefix . T.pack)
keyValToString :: Key -> Value -> String
keyValToString key value = toString key ++ " = " ++ json2Nix value ++ ";"
rawNixCode :: Either T.Text T.Text
rawNixCode = json2Nix <$> addErrPrefix "json2nix json error -\n" (A.eitherDecode $ BS.fromStrict input)
-- escapeDollar :: Text -> Text
-- escapeDollar = replace "''${" "\\''${"
formattedNixCode :: Either T.Text T.Text
formattedNixCode = (addErrPrefix "json2nix nixfmt error -\n" . format 80 "") =<< rawNixCode
json2Nix :: Value -> String
json2Nix (Object object) = "{" ++ foldMapWithKey keyValToString object ++ "}"
json2Nix (Array array) = "[" ++ foldr (\x y -> x ++ " " ++ y) "" (fmap json2Nix array) ++ "]"
json2Nix (Number n) = show n
json2Nix (Bool False) = "false"
json2Nix (Bool True) = "true"
json2Nix Null = "null"
json2Nix (String text) = sep ++ unpack text ++ sep
keyValToString :: A.Key -> A.Value -> T.Text
keyValToString key value = T.concat [T.pack $ show key, " = ", json2Nix value, ";"]
-- escapeDollar :: T.Text -> T.Text
-- escapeDollar = T.replace "''${" "\\''${"
json2Nix :: A.Value -> T.Text
json2Nix (A.Array array) = T.concat ["[", T.intercalate " " $ V.toList $ fmap json2Nix array, "]"]
json2Nix (A.Object object) = T.concat ["{", A.foldMapWithKey keyValToString object, "}"]
json2Nix (A.Number n) = T.pack $ show n
json2Nix (A.Bool False) = "false"
json2Nix (A.Bool True) = "true"
json2Nix A.Null = "null"
json2Nix (A.String text) = T.concat [sep, text, sep]
where
sep = if "\"" `isInfixOf` text then "\'\'" else "\""
sep = if "\"" `T.isInfixOf` text then "\'\'" else "\""

View File

@ -99,13 +99,13 @@ let
JSON_DATA=$(${jq} ".\"$OPTION_KEY\"" $JSON_MANUAL_PATH)
export DESCRIPTION=$(echo $JSON_DATA | ${jq} -r ".description" | ${perl} ${pArgs})
EXAMPLE_DATA=$(echo $JSON_DATA | ${jq} -r ".example.text" 2>/dev/null)
EXAMPLE_DATA=$(echo $JSON_DATA | ${jq} -r ".example.text" 2>/dev/null | ${nixfmt})
if [ $? != 0 ]; then
EXAMPLE_DATA=$(echo $JSON_DATA | ${jq} -r ".example" | ${json2nix}/bin/json2nix)
fi
export EXAMPLE=$(echo $EXAMPLE_DATA | ${nixfmt} | ${bat} ${batColorArg}--style=numbers)
export EXAMPLE=$(echo $EXAMPLE_DATA | ${bat} ${batColorArg}--style=numbers)
export DEFAULT=$(echo $JSON_DATA | ${jq} -r ".default" | ${json2nix}/bin/json2nix | ${nixfmt} | ${bat} ${batColorArg}--style=numbers)
export DEFAULT=$(echo $JSON_DATA | ${jq} -r ".default" | ${json2nix}/bin/json2nix | ${bat} ${batColorArg}--style=numbers)
echo $JSON_DATA | ${gomplate} --datasource opt=stdin:?type=application/json --file ${template}
'';