1 # This file is based on https://github.com/nix-community/home-manager
2 # Copyright (c) 2017-2022 Home Manager contributors
8 /* A partial and basic implementation of GVariant formatted strings.
9 See https://docs.gtk.org/glib/gvariant-format-strings.html for detauls.
11 Note, this API is not considered fully stable and it might therefore
12 change in backwards incompatible ways without prior notice.
16 concatMapStringsSep concatStrings escape head replaceStrings;
22 __toString = self: "@${self.type} ${toString self.value}"; # https://docs.gtk.org/glib/gvariant-text.html
28 tupleOf = ts: "(${concatStrings ts})";
29 dictionaryEntryOf = nameType: valueType: "{${nameType}${valueType}}";
43 /* Check if a value is a GVariant value
46 isGVariant :: Any -> Bool
48 isGVariant = v: v._type or "" == "gvariant";
53 inherit type isGVariant;
55 /* Returns the GVariant value that most closely matches the given Nix value.
56 If no GVariant value can be found unambiguously then error is thrown.
59 mkValue :: Any -> gvariant
62 if builtins.isBool v then
64 else if builtins.isFloat v then
66 else if builtins.isString v then
68 else if builtins.isList v then
70 else if isGVariant v then
73 throw "The GVariant type of ${v} can't be inferred.";
75 /* Returns the GVariant array from the given type of the elements and a Nix list.
78 mkArray :: [Any] -> gvariant
81 # Creating a string array
82 lib.gvariant.mkArray [ "a" "b" "c" ]
86 vs = map mkValue (lib.throwIf (elems == [ ]) "Please create empty array with mkEmptyArray." elems);
87 elemType = lib.throwIfNot (lib.all (t: (head vs).type == t) (map (v: v.type) vs))
88 "Elements in a list should have same type."
91 mkPrimitive (type.arrayOf elemType) vs // {
93 "@${self.type} [${concatMapStringsSep "," toString self.value}]";
96 /* Returns the GVariant array from the given empty Nix list.
99 mkEmptyArray :: gvariant.type -> gvariant
102 # Creating an empty string array
103 lib.gvariant.mkEmptyArray (lib.gvariant.type.string)
105 mkEmptyArray = elemType: mkPrimitive (type.arrayOf elemType) [ ] // {
106 __toString = self: "@${self.type} []";
110 /* Returns the GVariant variant from the given Nix value. Variants are containers
111 of different GVariant type.
114 mkVariant :: Any -> gvariant
117 lib.gvariant.mkArray [
118 (lib.gvariant.mkVariant "a string")
119 (lib.gvariant.mkVariant (lib.gvariant.mkInt32 1))
123 let gvarElem = mkValue elem;
124 in mkPrimitive type.variant gvarElem // {
125 __toString = self: "<${toString self.value}>";
128 /* Returns the GVariant dictionary entry from the given key and value.
131 mkDictionaryEntry :: String -> Any -> gvariant
134 # A dictionary describing an Epiphany’s search provider
136 (lib.gvariant.mkDictionaryEntry "url" (lib.gvariant.mkVariant "https://duckduckgo.com/?q=%s&t=epiphany"))
137 (lib.gvariant.mkDictionaryEntry "bang" (lib.gvariant.mkVariant "!d"))
138 (lib.gvariant.mkDictionaryEntry "name" (lib.gvariant.mkVariant "DuckDuckGo"))
142 # The key of the entry
144 # The value of the entry
147 name' = mkValue name;
148 value' = mkValue value;
149 dictionaryType = type.dictionaryEntryOf name'.type value'.type;
151 mkPrimitive dictionaryType { inherit name value; } // {
152 __toString = self: "@${self.type} {${name'},${value'}}";
155 /* Returns the GVariant maybe from the given element type.
158 mkMaybe :: gvariant.type -> Any -> gvariant
160 mkMaybe = elemType: elem:
161 mkPrimitive (type.maybeOf elemType) elem // {
163 if self.value == null then
164 "@${self.type} nothing"
166 "just ${toString self.value}";
169 /* Returns the GVariant nothing from the given element type.
172 mkNothing :: gvariant.type -> gvariant
174 mkNothing = elemType: mkMaybe elemType null;
176 /* Returns the GVariant just from the given Nix value.
179 mkJust :: Any -> gvariant
181 mkJust = elem: let gvarElem = mkValue elem; in mkMaybe gvarElem.type gvarElem;
183 /* Returns the GVariant tuple from the given Nix list.
186 mkTuple :: [Any] -> gvariant
190 gvarElems = map mkValue elems;
191 tupleType = type.tupleOf (map (e: e.type) gvarElems);
193 mkPrimitive tupleType gvarElems // {
195 "@${self.type} (${concatMapStringsSep "," toString self.value})";
198 /* Returns the GVariant boolean from the given Nix bool value.
201 mkBoolean :: Bool -> gvariant
204 mkPrimitive type.boolean v // {
205 __toString = self: if self.value then "true" else "false";
208 /* Returns the GVariant string from the given Nix string value.
211 mkString :: String -> gvariant
214 let sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
215 in mkPrimitive type.string v // {
216 __toString = self: "'${sanitize self.value}'";
219 /* Returns the GVariant object path from the given Nix string value.
222 mkObjectpath :: String -> gvariant
225 mkPrimitive type.string v // {
226 __toString = self: "objectpath '${escape [ "'" ] self.value}'";
229 /* Returns the GVariant uchar from the given Nix int value.
232 mkUchar :: Int -> gvariant
234 mkUchar = mkPrimitive type.uchar;
236 /* Returns the GVariant int16 from the given Nix int value.
239 mkInt16 :: Int -> gvariant
241 mkInt16 = mkPrimitive type.int16;
243 /* Returns the GVariant uint16 from the given Nix int value.
246 mkUint16 :: Int -> gvariant
248 mkUint16 = mkPrimitive type.uint16;
250 /* Returns the GVariant int32 from the given Nix int value.
253 mkInt32 :: Int -> gvariant
256 mkPrimitive type.int32 v // {
257 __toString = self: toString self.value;
260 /* Returns the GVariant uint32 from the given Nix int value.
263 mkUint32 :: Int -> gvariant
265 mkUint32 = mkPrimitive type.uint32;
267 /* Returns the GVariant int64 from the given Nix int value.
270 mkInt64 :: Int -> gvariant
272 mkInt64 = mkPrimitive type.int64;
274 /* Returns the GVariant uint64 from the given Nix int value.
277 mkUint64 :: Int -> gvariant
279 mkUint64 = mkPrimitive type.uint64;
281 /* Returns the GVariant double from the given Nix float value.
284 mkDouble :: Float -> gvariant
287 mkPrimitive type.double v // {
288 __toString = self: toString self.value;