From 49fcec8bf00378e2f6b118be0e8193386ae02d3d Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Mon, 15 Apr 2024 00:13:02 +0200 Subject: [PATCH] Improve support for typed values Using new `mkTyped` constructor, not yet supported by home-manager. dict also continues to be broken for now. --- data/typed.settings | 10 ++++++++++ output/dconf.nix | 2 +- output/typed.nix | 22 ++++++++++++++++++++++ output/variant.nix | 2 +- src/DConf.hs | 30 +++++++++++++++++++++++++++--- src/DConf/Data.hs | 1 + src/Nix.hs | 9 +++++++++ test/DConf2NixTest.hs | 11 +++++++++++ 8 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 data/typed.settings create mode 100644 output/typed.nix diff --git a/data/typed.settings b/data/typed.settings new file mode 100644 index 0000000..dd410d6 --- /dev/null +++ b/data/typed.settings @@ -0,0 +1,10 @@ +[typed] +empty-dict=@a{sv} {} +empty-array-dict=@a{sv} [] +just-str=@ms 'hello' +ui32=uint32 7 +at-u=@u 5 +empty-arr=@a(dd) [] +just-empty-str=@ms "" +doubletime=uint32 uint32 7 +var-empty-arr=<@ai []> diff --git a/output/dconf.nix b/output/dconf.nix index 80ca2c7..45a7270 100644 --- a/output/dconf.nix +++ b/output/dconf.nix @@ -334,7 +334,7 @@ with lib.hm.gvariant; }; "org/gnome/shell/world-clocks" = { - locations = []; + locations = mkArray "v" []; }; "org/gnome/software" = { diff --git a/output/typed.nix b/output/typed.nix new file mode 100644 index 0000000..3f4e75f --- /dev/null +++ b/output/typed.nix @@ -0,0 +1,22 @@ +# Generated via dconf2nix: https://github.com/nix-commmunity/dconf2nix +{ lib, ... }: + +with lib.hm.gvariant; + +{ + dconf.settings = { + "typed" = { + at-u = mkTyped "u" 5; + doubletime = mkUint32 7; + empty-arr = mkArray "(dd)" []; + empty-array-dict = mkArray "{sv}" []; + empty-dict = mkTyped "a{sv}" { + }; + just-empty-str = mkTyped "ms" ""; + just-str = mkTyped "ms" "hello"; + ui32 = mkUint32 7; + var-empty-arr = mkVariant (mkArray "i" []); + }; + + }; +} diff --git a/output/variant.nix b/output/variant.nix index d724fa0..3567454 100644 --- a/output/variant.nix +++ b/output/variant.nix @@ -13,7 +13,7 @@ with lib.hm.gvariant; string = mkVariant "#polari"; true = mkVariant true; tuple = mkVariant (mkTuple [ (mkUint32 2) "ABC" ]); - typed = mkVariant []; + typed = mkVariant (mkArray "i" []); uint32 = mkVariant (mkUint32 2); variant = mkVariant (mkVariant 7); }; diff --git a/src/DConf.hs b/src/DConf.hs index d45ddc7..113dff1 100644 --- a/src/DConf.hs +++ b/src/DConf.hs @@ -127,13 +127,37 @@ vVariant = fmap V $ bracket "<" ">" value vList :: Parsec Text () Value vList = fmap L $ bracket "[" "]" $ commaSeparated $ value +-- https://gitlab.gnome.org/GNOME/glib/-/blob/4607dd77a1944c6b29dff1e76c195f28a8ca12af/docs/reference/glib/gvariant-specification-1.0.rst#type-strings +typeString :: Parsec Text () String +typeString = baseType <|> containerType + where + baseType = choice (map string ["b", "y", "n", "q", "i", "u", "x", "t", "h", "d", "s", "o", "g"]) + containerType = variantType <|> maybeType <|> arrayType <|> tupleType <|> dictEntryType + types = many typeString + variantType = string "v" + arrayType = do + a <- string "a" + t <- typeString + return (a ++ t) + maybeType = do + m <- string "m" + t <- typeString + return (m ++ t) + tupleType = do + tt <- bracket "(" ")" types + return ("(" ++ concat tt ++ ")") + dictEntryType = bracket "{" "}" $ do + k <- baseType + v <- typeString + return ("{" ++ k ++ v ++ "}") + vTyped :: Parsec Text () Value vTyped = do _ <- char '@' - _ <- anyChar - _ <- anyChar + t <- typeString _ <- spaces - value + v <- value + return (Ty t v) vJson :: Parsec Text () Value vJson = try $ bracket "'" "'" $ do diff --git a/src/DConf/Data.hs b/src/DConf/Data.hs index 4b95ece..b00235b 100644 --- a/src/DConf/Data.hs +++ b/src/DConf/Data.hs @@ -21,6 +21,7 @@ data Value = S Text -- String | I64 Int -- Int64 | D Double -- Double | T [Value] -- Tuple of n-arity + | Ty String Value -- Typed value | L [Value] -- List of values | V Value -- Variant | R [(Text,Value)] -- Record diff --git a/src/Nix.hs b/src/Nix.hs index 5aa2edc..120ccc0 100644 --- a/src/Nix.hs +++ b/src/Nix.hs @@ -57,6 +57,9 @@ renderValue raw = Nix $ renderValue' raw <> ";" needsParen (D x) = x < 0 needsParen (I32 _) = True needsParen (T _) = True + -- will be rendered as @[]@ + needsParen (Ty "as" (L [])) = False + needsParen (Ty _ _) = True needsParen (V _) = True needsParen _ = False @@ -77,6 +80,12 @@ renderValue raw = Nix $ renderValue' raw <> ";" renderValue' (I64 v) = "mkInt64 " <> T.pack (show v) renderValue' (L xs) = renderList xs renderValue' (T xs) = "mkTuple " <> renderList xs + -- In home-manager, @mkValue []@ emits @\@as []@ + renderValue' (Ty "as" (L [])) = renderList [] + -- In home-manager, arrays are always typed when using @mkArray@. + renderValue' (Ty ('a':t) (L v)) = "mkArray " <> T.pack (show t) <> " " <> renderList v + -- TODO: add mkTyped to h-m + renderValue' (Ty t v) = "mkTyped " <> T.pack (show t) <> " " <> renderItem v renderValue' (V v) = "mkVariant " <> renderItem v renderValue' (Json v) = "''\n" <> mkSpaces 8 <> T.strip v <> "\n" <> mkSpaces 6 <> "''" diff --git a/test/DConf2NixTest.hs b/test/DConf2NixTest.hs index 1eedc3b..101e3ca 100644 --- a/test/DConf2NixTest.hs +++ b/test/DConf2NixTest.hs @@ -140,6 +140,17 @@ prop_dconf2nix_tuples :: Property prop_dconf2nix_tuples = withTests (10 :: TestLimit) dconf2nixTuples +dconf2nixTyped :: Property +dconf2nixTyped = + let input = "data/typed.settings" + output = "output/typed.nix" + root = Root T.empty + in baseProperty input output root + +prop_dconf2nix_typed :: Property +prop_dconf2nix_typed = + withTests (10 :: TestLimit) dconf2nixTyped + dconf2nixUnicode :: Property dconf2nixUnicode = let input = "data/unicode.settings"