master ohmu/fastfetch-openbsd / src / modules / packages / packages.c
ohmu  ·  2026-10-15
  1#include "common/printing.h"
  2#include "common/jsonconfig.h"
  3#include "common/strutil.h"
  4#include "detection/packages/packages.h"
  5#include "modules/packages/packages.h"
  6
  7bool ffPrintPackages(FFPackagesOptions* options) {
  8    FFPackagesResult counts = {};
  9    ffStrbufInit(&counts.pacmanBranch);
 10
 11    const char* error = ffDetectPackages(&counts, options);
 12
 13    if (error) {
 14        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
 15        return false;
 16    }
 17
 18    if (counts.all == 0) {
 19        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No packages from known package managers found");
 20        return false;
 21    }
 22
 23    uint32_t nixAll = counts.nixDefault + counts.nixSystem + counts.nixUser;
 24    uint32_t flatpakAll = counts.flatpakSystem + counts.flatpakUser;
 25    uint32_t brewAll = counts.brew + counts.brewCask;
 26    uint32_t guixAll = counts.guixSystem + counts.guixUser + counts.guixHome;
 27    uint32_t hpkgAll = counts.hpkgSystem + counts.hpkgUser;
 28    uint32_t amAll = counts.amSystem + counts.amUser;
 29    uint32_t scoopAll = counts.scoopUser + counts.scoopGlobal;
 30
 31    if (options->moduleArgs.outputFormat.length == 0) {
 32        ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
 33
 34        FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
 35
 36#define FF_PRINT_PACKAGE_NAME(var, name)           \
 37    if (counts.var > 0) {                          \
 38        ffStrbufAppendUInt(&output, counts.var);   \
 39        ffStrbufAppendS(&output, " (" name "), "); \
 40    }
 41
 42#define FF_PRINT_PACKAGE(name) FF_PRINT_PACKAGE_NAME(name, #name)
 43
 44#define FF_PRINT_PACKAGE_ALL(name)                  \
 45    if (name##All > 0) {                            \
 46        ffStrbufAppendUInt(&output, name##All);     \
 47        ffStrbufAppendS(&output, " (" #name "), "); \
 48    }
 49
 50        if (options->combined) {
 51            FF_PRINT_PACKAGE_ALL(am);
 52        } else {
 53            FF_PRINT_PACKAGE_NAME(amSystem, "am")
 54            FF_PRINT_PACKAGE_NAME(amUser, "appman")
 55        }
 56        FF_PRINT_PACKAGE(appimage)
 57        FF_PRINT_PACKAGE(apk)
 58        if (options->combined) {
 59            FF_PRINT_PACKAGE_ALL(brew);
 60        } else {
 61            FF_PRINT_PACKAGE_NAME(brew, "brew")
 62            FF_PRINT_PACKAGE_NAME(brewCask, "brew-cask")
 63        }
 64        FF_PRINT_PACKAGE(cards)
 65        FF_PRINT_PACKAGE(choco)
 66        FF_PRINT_PACKAGE(crux)
 67        FF_PRINT_PACKAGE(dpkg)
 68        FF_PRINT_PACKAGE(emerge)
 69        FF_PRINT_PACKAGE(eopkg)
 70        if (options->combined) {
 71            FF_PRINT_PACKAGE_ALL(flatpak);
 72        } else if (counts.flatpakUser > 0) {
 73            FF_PRINT_PACKAGE_NAME(flatpakSystem, "flatpak-system")
 74            FF_PRINT_PACKAGE_NAME(flatpakUser, "flatpak-user")
 75        } else {
 76            FF_PRINT_PACKAGE_NAME(flatpakSystem, "flatpak")
 77        }
 78        if (options->combined) {
 79            FF_PRINT_PACKAGE_ALL(guix);
 80        } else {
 81            FF_PRINT_PACKAGE_NAME(guixSystem, "guix-system")
 82            FF_PRINT_PACKAGE_NAME(guixUser, "guix-user")
 83            FF_PRINT_PACKAGE_NAME(guixHome, "guix-home")
 84        }
 85        if (options->combined) {
 86            FF_PRINT_PACKAGE_ALL(hpkg)
 87        } else if (counts.hpkgUser > 0) {
 88            FF_PRINT_PACKAGE_NAME(hpkgSystem, "hpkg-system")
 89            FF_PRINT_PACKAGE_NAME(hpkgUser, "hpkg-user")
 90        } else {
 91            FF_PRINT_PACKAGE_NAME(hpkgSystem, "hpkg")
 92        }
 93        FF_PRINT_PACKAGE_NAME(installrelease, "install-release")
 94        FF_PRINT_PACKAGE(kiss)
 95        FF_PRINT_PACKAGE(linglong)
 96        FF_PRINT_PACKAGE(lpkg)
 97        FF_PRINT_PACKAGE(lpkgbuild)
 98        FF_PRINT_PACKAGE(macports)
 99        FF_PRINT_PACKAGE(mport)
100        FF_PRINT_PACKAGE(moss)
101        if (options->combined) {
102            FF_PRINT_PACKAGE_ALL(nix);
103        } else {
104            FF_PRINT_PACKAGE_NAME(nixSystem, "nix-system")
105            FF_PRINT_PACKAGE_NAME(nixUser, "nix-user")
106            FF_PRINT_PACKAGE_NAME(nixDefault, "nix-default")
107        }
108        FF_PRINT_PACKAGE(opkg)
109        if (counts.pacman > 0) {
110            ffStrbufAppendF(&output, "%u (pacman)", counts.pacman);
111            if (counts.pacmanBranch.length > 0) {
112                ffStrbufAppendC(&output, '[');
113                ffStrbufAppend(&output, &counts.pacmanBranch);
114                ffStrbufAppendC(&output, ']');
115            }
116            ffStrbufAppendS(&output, ", ");
117        };
118        FF_PRINT_PACKAGE(pacstall)
119        FF_PRINT_PACKAGE(paludis)
120        FF_PRINT_PACKAGE(pisi)
121        FF_PRINT_PACKAGE(pkg)
122        FF_PRINT_PACKAGE(pkgsrc)
123        FF_PRINT_PACKAGE(pkgtool)
124        FF_PRINT_PACKAGE(porg)
125        FF_PRINT_PACKAGE(rpm)
126        FF_PRINT_PACKAGE(rum)
127        if (options->combined) {
128            FF_PRINT_PACKAGE_ALL(scoop);
129        } else if (counts.scoopGlobal > 0) {
130            FF_PRINT_PACKAGE_NAME(scoopUser, "scoop-user")
131            FF_PRINT_PACKAGE_NAME(scoopGlobal, "scoop-global")
132        } else {
133            FF_PRINT_PACKAGE_NAME(scoopUser, "scoop")
134        }
135        FF_PRINT_PACKAGE(snap)
136        FF_PRINT_PACKAGE(soar)
137        FF_PRINT_PACKAGE(sorcery)
138        FF_PRINT_PACKAGE(winget)
139        FF_PRINT_PACKAGE(xbps)
140
141        assert(output.length >= 2); // counts.all > 0 guarantees that at least one package count was printed, which guarantees that ", " was appended at least once
142        ffStrbufSubstrBefore(&output, output.length - 1);
143        output.chars[output.length - 1] = '\n';
144        ffStrbufWriteTo(&output, stdout);
145    } else {
146        FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Packages),
147            0,
148            &options->moduleArgs,
149            FF_PRINT_TYPE_DEFAULT,
150            ((FFformatarg[]) {
151                FF_ARG(counts.amSystem, "am-system"),
152                FF_ARG(counts.amUser, "am-user"),
153                FF_ARG(counts.appimage, "appimage"),
154                FF_ARG(counts.apk, "apk"),
155                FF_ARG(counts.brew, "brew"),
156                FF_ARG(counts.brewCask, "brew-cask"),
157                FF_ARG(counts.cards, "cards"),
158                FF_ARG(counts.choco, "choco"),
159                FF_ARG(counts.crux, "crux"),
160                FF_ARG(counts.dpkg, "dpkg"),
161                FF_ARG(counts.emerge, "emerge"),
162                FF_ARG(counts.eopkg, "eopkg"),
163                FF_ARG(counts.flatpakSystem, "flatpak-system"),
164                FF_ARG(counts.flatpakUser, "flatpak-user"),
165                FF_ARG(counts.guixHome, "guix-home"),
166                FF_ARG(counts.guixSystem, "guix-system"),
167                FF_ARG(counts.guixUser, "guix-user"),
168                FF_ARG(counts.hpkgSystem, "hpkg-system"),
169                FF_ARG(counts.hpkgUser, "hpkg-user"),
170                FF_ARG(counts.installrelease, "install-release"),
171                FF_ARG(counts.kiss, "kiss"),
172                FF_ARG(counts.linglong, "linglong"),
173                FF_ARG(counts.lpkg, "lpkg"),
174                FF_ARG(counts.lpkgbuild, "lpkgbuild"),
175                FF_ARG(counts.macports, "macports"),
176                FF_ARG(counts.mport, "mport"),
177                FF_ARG(counts.moss, "moss"),
178                FF_ARG(counts.nixDefault, "nix-default"),
179                FF_ARG(counts.nixSystem, "nix-system"),
180                FF_ARG(counts.nixUser, "nix-user"),
181                FF_ARG(counts.opkg, "opkg"),
182                FF_ARG(counts.pacman, "pacman"),
183                FF_ARG(counts.pacmanBranch, "pacman-branch"),
184                FF_ARG(counts.pacstall, "pacstall"),
185                FF_ARG(counts.paludis, "paludis"),
186                FF_ARG(counts.pisi, "pisi"),
187                FF_ARG(counts.pkg, "pkg"),
188                FF_ARG(counts.pkgsrc, "pkgsrc"),
189                FF_ARG(counts.pkgtool, "pkgtool"),
190                FF_ARG(counts.porg, "porg"),
191                FF_ARG(counts.rpm, "rpm"),
192                FF_ARG(counts.rum, "rum"),
193                FF_ARG(counts.scoopGlobal, "scoop-global"),
194                FF_ARG(counts.scoopUser, "scoop-user"),
195                FF_ARG(counts.snap, "snap"),
196                FF_ARG(counts.soar, "soar"),
197                FF_ARG(counts.sorcery, "sorcery"),
198                FF_ARG(counts.winget, "winget"),
199                FF_ARG(counts.xbps, "xbps"),
200
201                FF_ARG(brewAll, "brew-all"),
202                FF_ARG(flatpakAll, "flatpak-all"),
203                FF_ARG(guixAll, "guix-all"),
204                FF_ARG(hpkgAll, "hpkg-all"),
205                FF_ARG(nixAll, "nix-all"),
206                FF_ARG(counts.all, "all"),
207            }));
208    }
209
210    ffStrbufDestroy(&counts.pacmanBranch);
211
212    return true;
213}
214
215void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) {
216    yyjson_val *key, *val;
217    size_t idx, max;
218    yyjson_obj_foreach (module, idx, max, key, val) {
219        if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) {
220            continue;
221        }
222
223#if !FF_PACKAGES_REMOVE_DISABLED
224        if (unsafe_yyjson_equals_str(key, "disabled")) {
225            if (!yyjson_is_null(val) && !yyjson_is_arr(val)) {
226                ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key));
227                continue;
228            }
229
230            options->disabled = FF_PACKAGES_FLAG_NONE;
231
232            if (yyjson_is_arr(val)) {
233                yyjson_val* flagObj;
234                size_t flagIdx, flagMax;
235                yyjson_arr_foreach (val, flagIdx, flagMax, flagObj) {
236                    if (!yyjson_is_str(flagObj)) {
237                        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key));
238                        continue;
239                    }
240                    const char* flag = unsafe_yyjson_get_str(flagObj);
241
242    #define FF_TEST_PACKAGE_NAME(name)                          \
243        else if (ffStrEqualsIgnCase(flag, #name)) {             \
244            options->disabled |= FF_PACKAGES_FLAG_##name##_BIT; \
245        }
246                    switch (toupper(flag[0])) {
247                        case 'A':
248                            if (false)
249                                ;
250                            FF_TEST_PACKAGE_NAME(AM)
251                            FF_TEST_PACKAGE_NAME(APK)
252                            FF_TEST_PACKAGE_NAME(APPIMAGE)
253                            break;
254                        case 'B':
255                            if (false)
256                                ;
257                            FF_TEST_PACKAGE_NAME(BREW)
258                            break;
259                        case 'C':
260                            if (false)
261                                ;
262                            FF_TEST_PACKAGE_NAME(CARDS)
263                            FF_TEST_PACKAGE_NAME(CHOCO)
264                            FF_TEST_PACKAGE_NAME(CRUX)
265                            break;
266                        case 'D':
267                            if (false)
268                                ;
269                            FF_TEST_PACKAGE_NAME(DPKG)
270                            break;
271                        case 'E':
272                            if (false)
273                                ;
274                            FF_TEST_PACKAGE_NAME(EMERGE)
275                            FF_TEST_PACKAGE_NAME(EOPKG)
276                            break;
277                        case 'F':
278                            if (false)
279                                ;
280                            FF_TEST_PACKAGE_NAME(FLATPAK)
281                            break;
282                        case 'G':
283                            if (false)
284                                ;
285                            FF_TEST_PACKAGE_NAME(GUIX)
286                            break;
287                        case 'H':
288                            if (false)
289                                ;
290                            FF_TEST_PACKAGE_NAME(HPKG)
291                            break;
292                        case 'I':
293                            if (false)
294                                ;
295                            FF_TEST_PACKAGE_NAME(INSTALLRELEASE)
296                            break;
297                        case 'K':
298                            if (false)
299                                ;
300                            FF_TEST_PACKAGE_NAME(KISS)
301                            break;
302                        case 'L':
303                            if (false)
304                                ;
305                            FF_TEST_PACKAGE_NAME(LINGLONG)
306                            FF_TEST_PACKAGE_NAME(LPKG)
307                            FF_TEST_PACKAGE_NAME(LPKGBUILD)
308                            break;
309                        case 'M':
310                            if (false)
311                                ;
312                            FF_TEST_PACKAGE_NAME(MACPORTS)
313                            FF_TEST_PACKAGE_NAME(MOSS)
314                            FF_TEST_PACKAGE_NAME(MPORT)
315                            break;
316                        case 'N':
317                            if (false)
318                                ;
319                            FF_TEST_PACKAGE_NAME(NIX)
320                            break;
321                        case 'O':
322                            if (false)
323                                ;
324                            FF_TEST_PACKAGE_NAME(OPKG)
325                            break;
326                        case 'P':
327                            if (false)
328                                ;
329                            FF_TEST_PACKAGE_NAME(PACMAN)
330                            FF_TEST_PACKAGE_NAME(PACSTALL)
331                            FF_TEST_PACKAGE_NAME(PALUDIS)
332                            FF_TEST_PACKAGE_NAME(PISI)
333                            FF_TEST_PACKAGE_NAME(PKG)
334                            FF_TEST_PACKAGE_NAME(PKGSRC)
335                            FF_TEST_PACKAGE_NAME(PKGTOOL)
336                            FF_TEST_PACKAGE_NAME(PORG)
337                            break;
338                        case 'R':
339                            if (false)
340                                ;
341                            FF_TEST_PACKAGE_NAME(RPM)
342                            FF_TEST_PACKAGE_NAME(RUM)
343                            break;
344                        case 'S':
345                            if (false)
346                                ;
347                            FF_TEST_PACKAGE_NAME(SCOOP)
348                            FF_TEST_PACKAGE_NAME(SNAP)
349                            FF_TEST_PACKAGE_NAME(SOAR)
350                            FF_TEST_PACKAGE_NAME(SORCERY)
351                            break;
352                        case 'W':
353                            if (false)
354                                ;
355                            FF_TEST_PACKAGE_NAME(WINGET)
356                            break;
357                        case 'X':
358                            if (false)
359                                ;
360                            FF_TEST_PACKAGE_NAME(XBPS)
361                            break;
362                    }
363    #undef FF_TEST_PACKAGE_NAME
364                }
365                continue;
366            }
367        }
368#endif
369
370        if (unsafe_yyjson_equals_str(key, "combined")) {
371            options->combined = yyjson_get_bool(val);
372            continue;
373        }
374
375        ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
376    }
377}
378
379[[gnu::cold]]
380void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
381    ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
382
383#if !FF_PACKAGES_REMOVE_DISABLED
384    FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
385    yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "disabled");
386    #define FF_TEST_PACKAGE_NAME(name)                                  \
387        else if ((options->disabled & FF_PACKAGES_FLAG_##name##_BIT)) { \
388            ffStrbufSetS(&buf, #name);                                  \
389            ffStrbufLowerCase(&buf);                                    \
390            yyjson_mut_arr_add_strbuf(doc, arr, &buf);                  \
391        }
392    if (false)
393        ;
394    FF_TEST_PACKAGE_NAME(AM)
395    FF_TEST_PACKAGE_NAME(APK)
396    FF_TEST_PACKAGE_NAME(APPIMAGE)
397    FF_TEST_PACKAGE_NAME(BREW)
398    FF_TEST_PACKAGE_NAME(CARDS)
399    FF_TEST_PACKAGE_NAME(CHOCO)
400    FF_TEST_PACKAGE_NAME(CRUX)
401    FF_TEST_PACKAGE_NAME(DPKG)
402    FF_TEST_PACKAGE_NAME(EMERGE)
403    FF_TEST_PACKAGE_NAME(EOPKG)
404    FF_TEST_PACKAGE_NAME(FLATPAK)
405    FF_TEST_PACKAGE_NAME(GUIX)
406    FF_TEST_PACKAGE_NAME(HPKG)
407    FF_TEST_PACKAGE_NAME(KISS)
408    FF_TEST_PACKAGE_NAME(LINGLONG)
409    FF_TEST_PACKAGE_NAME(LPKG)
410    FF_TEST_PACKAGE_NAME(LPKGBUILD)
411    FF_TEST_PACKAGE_NAME(MACPORTS)
412    FF_TEST_PACKAGE_NAME(MOSS)
413    FF_TEST_PACKAGE_NAME(MPORT)
414    FF_TEST_PACKAGE_NAME(NIX)
415    FF_TEST_PACKAGE_NAME(OPKG)
416    FF_TEST_PACKAGE_NAME(PACMAN)
417    FF_TEST_PACKAGE_NAME(PACSTALL)
418    FF_TEST_PACKAGE_NAME(PALUDIS)
419    FF_TEST_PACKAGE_NAME(PISI)
420    FF_TEST_PACKAGE_NAME(PKG)
421    FF_TEST_PACKAGE_NAME(PKGSRC)
422    FF_TEST_PACKAGE_NAME(PKGTOOL)
423    FF_TEST_PACKAGE_NAME(PORG)
424    FF_TEST_PACKAGE_NAME(RPM)
425    FF_TEST_PACKAGE_NAME(RUM)
426    FF_TEST_PACKAGE_NAME(SCOOP)
427    FF_TEST_PACKAGE_NAME(SNAP)
428    FF_TEST_PACKAGE_NAME(SOAR)
429    FF_TEST_PACKAGE_NAME(SORCERY)
430    FF_TEST_PACKAGE_NAME(WINGET)
431    FF_TEST_PACKAGE_NAME(XBPS)
432    #undef FF_TEST_PACKAGE_NAME
433#endif
434
435    yyjson_mut_obj_add_bool(doc, module, "combined", options->combined);
436}
437
438bool ffGeneratePackagesJsonResult(FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
439    FFPackagesResult counts = {};
440    ffStrbufInit(&counts.pacmanBranch);
441
442    const char* error = ffDetectPackages(&counts, options);
443
444    if (error) {
445        yyjson_mut_obj_add_str(doc, module, "error", error);
446        return false;
447    }
448
449    yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
450
451    yyjson_mut_obj_add_uint(doc, obj, "all", counts.all);
452
453#define FF_APPEND_PACKAGE_COUNT(name) \
454    if (counts.name > 0) yyjson_mut_obj_add_uint(doc, obj, #name, counts.name);
455    FF_APPEND_PACKAGE_COUNT(amSystem)
456    FF_APPEND_PACKAGE_COUNT(amUser)
457    FF_APPEND_PACKAGE_COUNT(appimage)
458    FF_APPEND_PACKAGE_COUNT(apk)
459    FF_APPEND_PACKAGE_COUNT(brew)
460    FF_APPEND_PACKAGE_COUNT(brewCask)
461    FF_APPEND_PACKAGE_COUNT(cards)
462    FF_APPEND_PACKAGE_COUNT(choco)
463    FF_APPEND_PACKAGE_COUNT(crux)
464    FF_APPEND_PACKAGE_COUNT(dpkg)
465    FF_APPEND_PACKAGE_COUNT(emerge)
466    FF_APPEND_PACKAGE_COUNT(eopkg)
467    FF_APPEND_PACKAGE_COUNT(flatpakSystem)
468    FF_APPEND_PACKAGE_COUNT(flatpakUser)
469    FF_APPEND_PACKAGE_COUNT(guixHome)
470    FF_APPEND_PACKAGE_COUNT(guixSystem)
471    FF_APPEND_PACKAGE_COUNT(guixUser)
472    FF_APPEND_PACKAGE_COUNT(hpkgSystem)
473    FF_APPEND_PACKAGE_COUNT(hpkgUser)
474    FF_APPEND_PACKAGE_COUNT(installrelease)
475    FF_APPEND_PACKAGE_COUNT(kiss)
476    FF_APPEND_PACKAGE_COUNT(linglong)
477    FF_APPEND_PACKAGE_COUNT(lpkg)
478    FF_APPEND_PACKAGE_COUNT(lpkgbuild)
479    FF_APPEND_PACKAGE_COUNT(macports)
480    FF_APPEND_PACKAGE_COUNT(mport)
481    FF_APPEND_PACKAGE_COUNT(moss)
482    FF_APPEND_PACKAGE_COUNT(nixDefault)
483    FF_APPEND_PACKAGE_COUNT(nixSystem)
484    FF_APPEND_PACKAGE_COUNT(nixUser)
485    FF_APPEND_PACKAGE_COUNT(opkg)
486    FF_APPEND_PACKAGE_COUNT(pacman)
487    FF_APPEND_PACKAGE_COUNT(pacstall)
488    FF_APPEND_PACKAGE_COUNT(paludis)
489    FF_APPEND_PACKAGE_COUNT(pisi)
490    FF_APPEND_PACKAGE_COUNT(pkg)
491    FF_APPEND_PACKAGE_COUNT(pkgsrc)
492    FF_APPEND_PACKAGE_COUNT(pkgtool)
493    FF_APPEND_PACKAGE_COUNT(porg)
494    FF_APPEND_PACKAGE_COUNT(rpm)
495    FF_APPEND_PACKAGE_COUNT(rum)
496    FF_APPEND_PACKAGE_COUNT(scoopGlobal)
497    FF_APPEND_PACKAGE_COUNT(scoopUser)
498    FF_APPEND_PACKAGE_COUNT(snap)
499    FF_APPEND_PACKAGE_COUNT(soar)
500    FF_APPEND_PACKAGE_COUNT(sorcery)
501    FF_APPEND_PACKAGE_COUNT(winget)
502    FF_APPEND_PACKAGE_COUNT(xbps)
503    if (counts.pacmanBranch.length > 0) {
504        yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch);
505    }
506
507    return true;
508}
509
510void ffInitPackagesOptions(FFPackagesOptions* options) {
511    ffOptionInitModuleArg(&options->moduleArgs, "󰏖");
512
513    #if !FF_PACKAGES_REMOVE_DISABLED
514    options->disabled = FF_PACKAGES_DISABLE_LIST;
515    #endif
516    options->combined = false;
517}
518
519void ffDestroyPackagesOptions(FFPackagesOptions* options) {
520    ffOptionDestroyModuleArg(&options->moduleArgs);
521}
522
523FFModuleBaseInfo ffPackagesModuleInfo = {
524    .name = "Packages",
525    .description = "List installed package managers and count of installed packages",
526    .displayName = {
527        .en = "Packages",
528        .ar = "الحزم",
529        .cs = "Balíčky",
530        .de = "Pakete",
531        .es = "Paquetes",
532        .fi = "Ohjelmistopaketit",
533        .fr = "Paquets",
534        .gl = "Paquetes",
535        .he = "חבילות",
536        .id = "Paket",
537        .it = "Pacchetti",
538        .ja = "パッケージ",
539        .ko = "패키지",
540        .pl = "Pakiety",
541        .pt = "Pacotes",
542        .ru = "Пакеты",
543        .tr = "Paketler",
544        .uk = "Пакети",
545        .vi = "Gói phần mềm",
546        .zh_CN = "软件包",
547        .zh_TW = "軟體包",
548    },
549    .initOptions = (void*) ffInitPackagesOptions,
550    .destroyOptions = (void*) ffDestroyPackagesOptions,
551    .parseJsonObject = (void*) ffParsePackagesJsonObject,
552    .printModule = (void*) ffPrintPackages,
553    .generateJsonResult = (void*) ffGeneratePackagesJsonResult,
554    .generateJsonConfig = (void*) ffGeneratePackagesJsonConfig,
555    .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
556        { "Number of am-system packages", "am-system" },
557        { "Number of am-user (aka appman) packages", "am-user" },
558        { "Number of appimage packages", "appimage" },
559        { "Number of apk packages", "apk" },
560        { "Number of brew packages", "brew" },
561        { "Number of brew-cask packages", "brew-cask" },
562        { "Number of cards packages", "cards" },
563        { "Number of choco packages", "choco" },
564        { "Number of crux packages", "crux" },
565        { "Number of dpkg packages", "dpkg" },
566        { "Number of emerge packages", "emerge" },
567        { "Number of eopkg packages", "eopkg" },
568        { "Number of flatpak-system app packages", "flatpak-system" },
569        { "Number of flatpak-user app packages", "flatpak-user" },
570        { "Number of guix-home packages", "guix-home" },
571        { "Number of guix-system packages", "guix-system" },
572        { "Number of guix-user packages", "guix-user" },
573        { "Number of hpkg-system packages", "hpkg-system" },
574        { "Number of hpkg-user packages", "hpkg-user" },
575        { "Number of install-release packages", "install-release" },
576        { "Number of kiss packages", "kiss" },
577        { "Number of linglong packages", "linglong" },
578        { "Number of lpkg packages", "lpkg" },
579        { "Number of lpkgbuild packages", "lpkgbuild" },
580        { "Number of macports packages", "macports" },
581        { "Number of mport packages", "mport" },
582        { "Number of moss packages", "moss" },
583        { "Number of nix-default packages", "nix-default" },
584        { "Number of nix-system packages", "nix-system" },
585        { "Number of nix-user packages", "nix-user" },
586        { "Number of opkg packages", "opkg" },
587        { "Number of pacman packages", "pacman" },
588        { "Pacman branch on manjaro", "pacman-branch" },
589        { "Number of pacstall packages", "pacstall" },
590        { "Number of paludis packages", "paludis" },
591        { "Number of pisi packages", "pisi" },
592        { "Number of pkg packages", "pkg" },
593        { "Number of pkgsrc packages", "pkgsrc" },
594        { "Number of pkgtool packages", "pkgtool" },
595        { "Number of porg packages", "porg" },
596        { "Number of rpm packages", "rpm" },
597        { "Number of rum overlay packages", "rum" },
598        { "Number of scoop-global packages", "scoop-global" },
599        { "Number of scoop-user packages", "scoop-user" },
600        { "Number of snap packages", "snap" },
601        { "Number of soar packages", "soar" },
602        { "Number of sorcery packages", "sorcery" },
603        { "Number of winget packages", "winget" },
604        { "Number of xbps packages", "xbps" },
605
606        { "Total number of all brew packages", "brew-all" },
607        { "Total number of all flatpak app packages", "flatpak-all" },
608        { "Total number of all guix packages", "guix-all" },
609        { "Total number of all hpkg packages", "hpkg-all" },
610        { "Total number of all nix packages", "nix-all" },
611        { "Number of all packages", "all" },
612    })),
613    .defaultOrder = 14,
614};