formalconf 2.0.21 → 2.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/formalconf.js +231 -19
  2. package/package.json +1 -1
@@ -1,12 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
3
7
  var __export = (target, all) => {
4
8
  for (var name in all)
5
9
  __defProp(target, name, {
6
10
  get: all[name],
7
11
  enumerable: true,
8
12
  configurable: true,
9
- set: (newValue) => all[name] = () => newValue
13
+ set: __exportSetter.bind(all, name)
10
14
  });
11
15
  };
12
16
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -457,7 +461,7 @@ async function isFirstRun() {
457
461
  const themesExist = await dirHasContents(THEMES_DIR);
458
462
  return !configsExist && !themesExist;
459
463
  }
460
- var HOME_DIR, CONFIG_DIR, THEME_TARGET_DIR, BACKGROUNDS_TARGET_DIR, scriptPath, ROOT_DIR, CONFIGS_DIR, THEMES_DIR, HOOKS_DIR, PKG_CONFIG_PATH, PKG_LOCK_PATH, THEME_CONFIG_PATH, TEMPLATES_DIR, TEMPLATES_MANIFEST_PATH, GENERATED_DIR, BUNDLED_TEMPLATES_DIR, BUNDLED_MANIFEST_PATH, GTK_DIR, COLLOID_DIR, QT_DIR, KVANTUM_CONFIG_DIR, KVANTUM_THEME_DIR;
464
+ var HOME_DIR, CONFIG_DIR, THEME_TARGET_DIR, BACKGROUNDS_TARGET_DIR, scriptPath, ROOT_DIR, CONFIGS_DIR, THEMES_DIR, HOOKS_DIR, PKG_CONFIG_PATH, PKG_LOCK_PATH, THEME_CONFIG_PATH, TEMPLATES_DIR, TEMPLATES_MANIFEST_PATH, GENERATED_DIR, BUNDLED_TEMPLATES_DIR, BUNDLED_MANIFEST_PATH, GTK_DIR, COLLOID_DIR, GTK_OVERRIDES_DIR, QT_DIR, KVANTUM_CONFIG_DIR, KVANTUM_THEME_DIR;
461
465
  var init_paths = __esm(() => {
462
466
  init_runtime();
463
467
  init_platform();
@@ -480,6 +484,7 @@ var init_paths = __esm(() => {
480
484
  BUNDLED_MANIFEST_PATH = join(BUNDLED_TEMPLATES_DIR, "templates.json");
481
485
  GTK_DIR = join(CONFIG_DIR, "gtk");
482
486
  COLLOID_DIR = join(GTK_DIR, "colloid-gtk-theme");
487
+ GTK_OVERRIDES_DIR = join(GTK_DIR, "overrides");
483
488
  QT_DIR = join(CONFIG_DIR, "qt");
484
489
  KVANTUM_CONFIG_DIR = join(HOME_DIR, ".config", "Kvantum");
485
490
  KVANTUM_THEME_DIR = join(KVANTUM_CONFIG_DIR, "FormalConf");
@@ -3026,6 +3031,8 @@ $default-dark: ${colloid.accent.dark};
3026
3031
  // src/lib/gtk/colloid.ts
3027
3032
  import { existsSync as existsSync7 } from "fs";
3028
3033
  import { join as join6 } from "path";
3034
+ import { symlink, unlink, lstat } from "fs/promises";
3035
+ import { homedir as homedir2 } from "os";
3029
3036
  async function checkGtkDependencies() {
3030
3037
  const [git, sassc] = await Promise.all([
3031
3038
  commandExists("git"),
@@ -3117,6 +3124,46 @@ function getGtkThemeName(themeName, mode) {
3117
3124
  const modeCapitalized = mode === "dark" ? "Dark" : "Light";
3118
3125
  return `formalconf-${themeName}-${modeCapitalized}`;
3119
3126
  }
3127
+ async function applyGtkOverride(overrideName, mode) {
3128
+ const overrideDir = join6(GTK_OVERRIDES_DIR, overrideName);
3129
+ if (!existsSync7(overrideDir)) {
3130
+ return {
3131
+ success: false,
3132
+ themeName: "",
3133
+ error: `GTK override "${overrideName}" not found in ${GTK_OVERRIDES_DIR}`
3134
+ };
3135
+ }
3136
+ const installTarget = join6(homedir2(), ".local", "share", "themes", overrideName);
3137
+ await ensureDir2(join6(homedir2(), ".local", "share", "themes"));
3138
+ try {
3139
+ const stat = await lstat(installTarget);
3140
+ if (stat.isSymbolicLink() || stat.isDirectory()) {
3141
+ await unlink(installTarget);
3142
+ }
3143
+ } catch {}
3144
+ await symlink(overrideDir, installTarget, "dir");
3145
+ const hasGsettings = await commandExists("gsettings");
3146
+ if (hasGsettings) {
3147
+ await exec([
3148
+ "gsettings",
3149
+ "set",
3150
+ "org.gnome.desktop.interface",
3151
+ "gtk-theme",
3152
+ overrideName
3153
+ ]);
3154
+ await exec([
3155
+ "gsettings",
3156
+ "set",
3157
+ "org.gnome.desktop.interface",
3158
+ "color-scheme",
3159
+ `prefer-${mode}`
3160
+ ]);
3161
+ }
3162
+ return {
3163
+ success: true,
3164
+ themeName: overrideName
3165
+ };
3166
+ }
3120
3167
  async function applyGtkTheme(theme, mode) {
3121
3168
  if (getOS() !== "linux") {
3122
3169
  return {
@@ -3126,6 +3173,10 @@ async function applyGtkTheme(theme, mode) {
3126
3173
  skipReason: "GTK theming only available on Linux"
3127
3174
  };
3128
3175
  }
3176
+ const overrideName = theme.gtk?.override?.[mode];
3177
+ if (overrideName) {
3178
+ return applyGtkOverride(overrideName, mode);
3179
+ }
3129
3180
  const palette = mode === "dark" ? theme.dark : theme.light;
3130
3181
  if (!palette) {
3131
3182
  return {
@@ -5569,8 +5620,162 @@ var init_template_manager = __esm(() => {
5569
5620
  }
5570
5621
  });
5571
5622
 
5623
+ // src/cli/gtk-manager.ts
5624
+ var exports_gtk_manager = {};
5625
+ __export(exports_gtk_manager, {
5626
+ main: () => main6
5627
+ });
5628
+ import { parseArgs as parseArgs6 } from "util";
5629
+ import { existsSync as existsSync15, statSync as statSync2 } from "fs";
5630
+ import { join as join14, resolve, basename as basename5 } from "path";
5631
+ import { readdir as readdir2, rename, rm } from "fs/promises";
5632
+ import { tmpdir } from "os";
5633
+ function printHelp2() {
5634
+ console.log(`
5635
+ ${colors7.cyan}GTK Theme Manager - Manage pre-built GTK theme overrides${colors7.reset}
5636
+
5637
+ Usage:
5638
+ formalconf gtk <command> [options]
5639
+
5640
+ Commands:
5641
+ ${colors7.blue}import${colors7.reset} <path.tar.gz> Import a GTK theme from a tar.gz archive
5642
+ ${colors7.blue}list${colors7.reset} List installed GTK override themes
5643
+ ${colors7.blue}remove${colors7.reset} <name> Remove an installed GTK override theme
5644
+
5645
+ Options:
5646
+ -h, --help Show this help message
5647
+
5648
+ Examples:
5649
+ formalconf gtk import ~/Downloads/Kanagawa_Dark.tar.gz
5650
+ formalconf gtk list
5651
+ formalconf gtk remove "Kanagawa Dark"
5652
+ `);
5653
+ }
5654
+ async function main6() {
5655
+ const { positionals, values } = parseArgs6({
5656
+ args: process.argv.slice(2),
5657
+ options: {
5658
+ help: { type: "boolean", short: "h" }
5659
+ },
5660
+ allowPositionals: true,
5661
+ strict: false
5662
+ });
5663
+ const [subCommand, ...args] = positionals;
5664
+ if (values.help || !subCommand) {
5665
+ printHelp2();
5666
+ process.exit(0);
5667
+ }
5668
+ switch (subCommand) {
5669
+ case "import":
5670
+ if (!args[0]) {
5671
+ console.error(`${colors7.red}Error: Path to tar.gz file required${colors7.reset}`);
5672
+ process.exit(1);
5673
+ }
5674
+ await handleImport(args[0]);
5675
+ break;
5676
+ case "list":
5677
+ await handleList2();
5678
+ break;
5679
+ case "remove":
5680
+ if (!args[0]) {
5681
+ console.error(`${colors7.red}Error: Theme name required${colors7.reset}`);
5682
+ process.exit(1);
5683
+ }
5684
+ await handleRemove(args[0]);
5685
+ break;
5686
+ default:
5687
+ console.error(`${colors7.red}Unknown command: ${subCommand}${colors7.reset}`);
5688
+ printHelp2();
5689
+ process.exit(1);
5690
+ }
5691
+ }
5692
+ async function handleImport(archivePath) {
5693
+ const resolved = resolve(archivePath);
5694
+ if (!existsSync15(resolved)) {
5695
+ console.error(`${colors7.red}Error: File not found: ${resolved}${colors7.reset}`);
5696
+ process.exit(1);
5697
+ }
5698
+ if (!resolved.endsWith(".tar.gz") && !resolved.endsWith(".tgz")) {
5699
+ console.error(`${colors7.red}Error: File must be a .tar.gz or .tgz archive${colors7.reset}`);
5700
+ process.exit(1);
5701
+ }
5702
+ const tempDir = join14(tmpdir(), `formalconf-gtk-import-${Date.now()}`);
5703
+ await ensureDir2(tempDir);
5704
+ console.log(`${colors7.cyan}Extracting ${basename5(resolved)}...${colors7.reset}`);
5705
+ const extractResult = await exec(["tar", "xzf", resolved, "-C", tempDir]);
5706
+ if (!extractResult.success) {
5707
+ console.error(`${colors7.red}Error: Failed to extract archive${colors7.reset}`);
5708
+ await rm(tempDir, { recursive: true, force: true });
5709
+ process.exit(1);
5710
+ }
5711
+ const entries = await readdir2(tempDir);
5712
+ const dirs = entries.filter((entry) => statSync2(join14(tempDir, entry)).isDirectory());
5713
+ if (dirs.length === 0) {
5714
+ console.error(`${colors7.red}Error: Archive contains no directories${colors7.reset}`);
5715
+ await rm(tempDir, { recursive: true, force: true });
5716
+ process.exit(1);
5717
+ }
5718
+ await ensureDir2(GTK_OVERRIDES_DIR);
5719
+ for (const dir of dirs) {
5720
+ const sourcePath = join14(tempDir, dir);
5721
+ const destPath = join14(GTK_OVERRIDES_DIR, dir);
5722
+ if (existsSync15(destPath)) {
5723
+ await rm(destPath, { recursive: true, force: true });
5724
+ }
5725
+ await rename(sourcePath, destPath);
5726
+ console.log(`${colors7.green}Imported: ${dir}${colors7.reset}`);
5727
+ console.log(`${colors7.dim} Use in theme JSON: "gtk": { "override": { "dark": "${dir}" } }${colors7.reset}`);
5728
+ }
5729
+ await rm(tempDir, { recursive: true, force: true });
5730
+ }
5731
+ async function handleList2() {
5732
+ if (!existsSync15(GTK_OVERRIDES_DIR)) {
5733
+ console.log(`${colors7.dim}No GTK overrides installed${colors7.reset}`);
5734
+ return;
5735
+ }
5736
+ const entries = await readdir2(GTK_OVERRIDES_DIR);
5737
+ const dirs = entries.filter((entry) => statSync2(join14(GTK_OVERRIDES_DIR, entry)).isDirectory());
5738
+ if (dirs.length === 0) {
5739
+ console.log(`${colors7.dim}No GTK overrides installed${colors7.reset}`);
5740
+ return;
5741
+ }
5742
+ console.log(`
5743
+ ${colors7.cyan}Installed GTK overrides:${colors7.reset}`);
5744
+ for (const dir of dirs) {
5745
+ console.log(` ${colors7.blue}•${colors7.reset} ${dir}`);
5746
+ }
5747
+ console.log();
5748
+ }
5749
+ async function handleRemove(name) {
5750
+ const targetPath = join14(GTK_OVERRIDES_DIR, name);
5751
+ if (!existsSync15(targetPath)) {
5752
+ console.error(`${colors7.red}Error: Override "${name}" not found${colors7.reset}`);
5753
+ process.exit(1);
5754
+ }
5755
+ await rm(targetPath, { recursive: true, force: true });
5756
+ console.log(`${colors7.green}Removed: ${name}${colors7.reset}`);
5757
+ }
5758
+ var colors7, isMainModule6;
5759
+ var init_gtk_manager = __esm(() => {
5760
+ init_paths();
5761
+ init_runtime();
5762
+ colors7 = {
5763
+ red: "\x1B[0;31m",
5764
+ green: "\x1B[0;32m",
5765
+ blue: "\x1B[0;34m",
5766
+ yellow: "\x1B[1;33m",
5767
+ cyan: "\x1B[0;36m",
5768
+ dim: "\x1B[2m",
5769
+ reset: "\x1B[0m"
5770
+ };
5771
+ isMainModule6 = process.argv[1]?.includes("gtk-manager");
5772
+ if (isMainModule6) {
5773
+ main6().catch(console.error);
5774
+ }
5775
+ });
5776
+
5572
5777
  // src/cli/formalconf.tsx
5573
- import { parseArgs as parseArgs6 } from "node:util";
5778
+ import { parseArgs as parseArgs7 } from "node:util";
5574
5779
  import { useState as useState11, useEffect as useEffect7 } from "react";
5575
5780
  import { render, useApp as useApp2, useInput as useInput11 } from "ink";
5576
5781
  import { Spinner as Spinner2 } from "@inkjs/ui";
@@ -5713,7 +5918,7 @@ function StatusIndicator({
5713
5918
  // package.json
5714
5919
  var package_default = {
5715
5920
  name: "formalconf",
5716
- version: "2.0.21",
5921
+ version: "2.0.22",
5717
5922
  description: "Dotfiles management TUI for macOS and Linux - config management, package sync, and theme switching",
5718
5923
  type: "module",
5719
5924
  main: "./dist/formalconf.js",
@@ -7937,7 +8142,7 @@ function ThemeMenu({ onBack }) {
7937
8142
  init_paths();
7938
8143
  init_runtime();
7939
8144
  import { jsxDEV as jsxDEV20 } from "react/jsx-dev-runtime";
7940
- function printHelp2() {
8145
+ function printHelp3() {
7941
8146
  console.log(`
7942
8147
  FormalConf - Dotfiles Management TUI
7943
8148
 
@@ -7947,6 +8152,7 @@ Usage:
7947
8152
  formalconf config <cmd> Config management (stow, unstow, status, list)
7948
8153
  formalconf pkg-sync [flags] Sync packages from pkg-config.json
7949
8154
  formalconf template <cmd> Template management (update, list, check)
8155
+ formalconf gtk <cmd> GTK override management (import, list, remove)
7950
8156
 
7951
8157
  Options:
7952
8158
  -h, --help Show this help message
@@ -8032,8 +8238,8 @@ function App() {
8032
8238
  ]
8033
8239
  }, undefined, true, undefined, this);
8034
8240
  }
8035
- async function main6() {
8036
- const { positionals, values } = parseArgs6({
8241
+ async function main7() {
8242
+ const { positionals, values } = parseArgs7({
8037
8243
  args: process.argv.slice(2),
8038
8244
  options: {
8039
8245
  help: { type: "boolean", short: "h" }
@@ -8043,7 +8249,7 @@ async function main6() {
8043
8249
  });
8044
8250
  const [subcommand] = positionals;
8045
8251
  if (values.help && !subcommand) {
8046
- printHelp2();
8252
+ printHelp3();
8047
8253
  process.exit(0);
8048
8254
  }
8049
8255
  if (subcommand) {
@@ -8051,34 +8257,40 @@ async function main6() {
8051
8257
  theme: "set-theme",
8052
8258
  config: "config-manager",
8053
8259
  "pkg-sync": "pkg-sync",
8054
- template: "template-manager"
8260
+ template: "template-manager",
8261
+ gtk: "gtk-manager"
8055
8262
  };
8056
8263
  const scriptName = scriptMap[subcommand];
8057
8264
  if (!scriptName) {
8058
8265
  console.error(`Unknown subcommand: ${subcommand}`);
8059
- printHelp2();
8266
+ printHelp3();
8060
8267
  process.exit(1);
8061
8268
  }
8062
8269
  process.argv = [process.argv[0], scriptName, ...process.argv.slice(3)];
8063
8270
  switch (subcommand) {
8064
8271
  case "theme": {
8065
- const { main: main7 } = await Promise.resolve().then(() => (init_set_theme(), exports_set_theme));
8066
- await main7();
8272
+ const { main: main8 } = await Promise.resolve().then(() => (init_set_theme(), exports_set_theme));
8273
+ await main8();
8067
8274
  break;
8068
8275
  }
8069
8276
  case "config": {
8070
- const { main: main7 } = await Promise.resolve().then(() => (init_config_manager(), exports_config_manager));
8071
- await main7();
8277
+ const { main: main8 } = await Promise.resolve().then(() => (init_config_manager(), exports_config_manager));
8278
+ await main8();
8072
8279
  break;
8073
8280
  }
8074
8281
  case "pkg-sync": {
8075
- const { main: main7 } = await Promise.resolve().then(() => (init_pkg_sync(), exports_pkg_sync));
8076
- await main7();
8282
+ const { main: main8 } = await Promise.resolve().then(() => (init_pkg_sync(), exports_pkg_sync));
8283
+ await main8();
8077
8284
  break;
8078
8285
  }
8079
8286
  case "template": {
8080
- const { main: main7 } = await Promise.resolve().then(() => (init_template_manager(), exports_template_manager));
8081
- await main7();
8287
+ const { main: main8 } = await Promise.resolve().then(() => (init_template_manager(), exports_template_manager));
8288
+ await main8();
8289
+ break;
8290
+ }
8291
+ case "gtk": {
8292
+ const { main: main8 } = await Promise.resolve().then(() => (init_gtk_manager(), exports_gtk_manager));
8293
+ await main8();
8082
8294
  break;
8083
8295
  }
8084
8296
  }
@@ -8086,4 +8298,4 @@ async function main6() {
8086
8298
  }
8087
8299
  render(/* @__PURE__ */ jsxDEV20(App, {}, undefined, false, undefined, this));
8088
8300
  }
8089
- main6();
8301
+ main7();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "formalconf",
3
- "version": "2.0.21",
3
+ "version": "2.0.22",
4
4
  "description": "Dotfiles management TUI for macOS and Linux - config management, package sync, and theme switching",
5
5
  "type": "module",
6
6
  "main": "./dist/formalconf.js",