formalconf 2.0.2 → 2.0.3
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.
- package/LICENSE +21 -0
- package/dist/formalconf.js +669 -155
- package/package.json +1 -1
package/dist/formalconf.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// src/cli/formalconf.tsx
|
|
3
|
-
import { useState as
|
|
4
|
-
import { render, useApp as useApp2, useInput as
|
|
3
|
+
import { useState as useState10, useEffect as useEffect6 } from "react";
|
|
4
|
+
import { render, useApp as useApp2, useInput as useInput10 } from "ink";
|
|
5
5
|
import { Spinner as Spinner2 } from "@inkjs/ui";
|
|
6
6
|
|
|
7
7
|
// src/components/layout/Layout.tsx
|
|
@@ -41,6 +41,7 @@ import { existsSync, readlinkSync, readdirSync, lstatSync } from "fs";
|
|
|
41
41
|
// src/lib/paths.ts
|
|
42
42
|
import { homedir } from "os";
|
|
43
43
|
import { join } from "path";
|
|
44
|
+
import { readdir } from "fs/promises";
|
|
44
45
|
|
|
45
46
|
// src/lib/runtime.ts
|
|
46
47
|
import { spawn as nodeSpawn } from "child_process";
|
|
@@ -294,6 +295,19 @@ async function ensureConfigDir() {
|
|
|
294
295
|
await ensureDir2(THEME_TARGET_DIR);
|
|
295
296
|
await ensureDir2(BACKGROUNDS_TARGET_DIR);
|
|
296
297
|
}
|
|
298
|
+
async function dirHasContents(path) {
|
|
299
|
+
try {
|
|
300
|
+
const entries = await readdir(path);
|
|
301
|
+
return entries.length > 0;
|
|
302
|
+
} catch {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
async function isFirstRun() {
|
|
307
|
+
const configsExist = await dirHasContents(CONFIGS_DIR);
|
|
308
|
+
const themesExist = await dirHasContents(THEMES_DIR);
|
|
309
|
+
return !configsExist && !themesExist;
|
|
310
|
+
}
|
|
297
311
|
|
|
298
312
|
// src/hooks/useSystemStatus.ts
|
|
299
313
|
import { basename, dirname as dirname2, join as join2 } from "path";
|
|
@@ -400,7 +414,7 @@ function StatusIndicator({
|
|
|
400
414
|
// package.json
|
|
401
415
|
var package_default = {
|
|
402
416
|
name: "formalconf",
|
|
403
|
-
version: "2.0.
|
|
417
|
+
version: "2.0.3",
|
|
404
418
|
description: "Dotfiles management TUI for macOS - config management, package sync, and theme switching",
|
|
405
419
|
type: "module",
|
|
406
420
|
main: "./dist/formalconf.js",
|
|
@@ -684,8 +698,9 @@ function PrerequisiteError({ missing, onExit }) {
|
|
|
684
698
|
}, undefined, false, undefined, this);
|
|
685
699
|
}
|
|
686
700
|
|
|
687
|
-
// src/components/
|
|
688
|
-
import {
|
|
701
|
+
// src/components/Onboarding.tsx
|
|
702
|
+
import { useState as useState4 } from "react";
|
|
703
|
+
import { Box as Box9, Text as Text8, useInput as useInput3 } from "ink";
|
|
689
704
|
|
|
690
705
|
// src/components/ui/VimSelect.tsx
|
|
691
706
|
import { useState as useState3 } from "react";
|
|
@@ -721,13 +736,502 @@ function VimSelect({ options, onChange, isDisabled = false }) {
|
|
|
721
736
|
}, undefined, false, undefined, this);
|
|
722
737
|
}
|
|
723
738
|
|
|
724
|
-
// src/
|
|
739
|
+
// src/lib/templates.ts
|
|
740
|
+
import { join as join3 } from "path";
|
|
741
|
+
import { existsSync as existsSync2 } from "fs";
|
|
742
|
+
var EXAMPLE_CONFIG_README = `# Example Stow Config Package
|
|
743
|
+
|
|
744
|
+
This is an example dotfiles package for use with GNU Stow.
|
|
745
|
+
|
|
746
|
+
## Structure
|
|
747
|
+
Files are organized to mirror your home directory:
|
|
748
|
+
- \`.config/example-app/config.toml\` -> \`~/.config/example-app/config.toml\`
|
|
749
|
+
- \`.example-app-rc\` -> \`~/.example-app-rc\`
|
|
750
|
+
|
|
751
|
+
## Usage
|
|
752
|
+
1. Place your dotfiles in this directory structure
|
|
753
|
+
2. Run \`formalconf\` and use Config Manager -> Stow
|
|
754
|
+
3. Symlinks will be created from your home directory
|
|
755
|
+
|
|
756
|
+
## Creating Your Own
|
|
757
|
+
1. Copy this directory and rename it (e.g., \`git\`, \`zsh\`, \`nvim\`)
|
|
758
|
+
2. Add your dotfiles mirroring your home directory structure
|
|
759
|
+
3. Stow the package to create symlinks
|
|
760
|
+
`;
|
|
761
|
+
var EXAMPLE_CONFIG_TOML = `# Example configuration file
|
|
762
|
+
# This will be symlinked to ~/.config/example-app/config.toml
|
|
763
|
+
|
|
764
|
+
[settings]
|
|
765
|
+
theme = "default"
|
|
766
|
+
auto_save = true
|
|
767
|
+
|
|
768
|
+
[keybindings]
|
|
769
|
+
quit = "q"
|
|
770
|
+
save = "ctrl+s"
|
|
771
|
+
`;
|
|
772
|
+
var EXAMPLE_RC = `# Example rc file
|
|
773
|
+
# This will be symlinked to ~/.example-app-rc
|
|
774
|
+
export EXAMPLE_VAR="hello"
|
|
775
|
+
`;
|
|
776
|
+
var EXAMPLE_THEME_YAML = `name: Example Theme
|
|
777
|
+
author: Your Name
|
|
778
|
+
description: A template theme for FormalConf
|
|
779
|
+
version: 1.0.0
|
|
780
|
+
|
|
781
|
+
colors:
|
|
782
|
+
primary: "#5eead4"
|
|
783
|
+
secondary: "#2dd4bf"
|
|
784
|
+
background: "#1a1a2e"
|
|
785
|
+
foreground: "#e4e4e7"
|
|
786
|
+
accent: "#06b6d4"
|
|
787
|
+
`;
|
|
788
|
+
var EXAMPLE_NEOVIM_LUA = `-- Neovim colorscheme configuration
|
|
789
|
+
-- This file is symlinked when the theme is applied
|
|
790
|
+
return {
|
|
791
|
+
{
|
|
792
|
+
"your-colorscheme/nvim",
|
|
793
|
+
name = "example-theme",
|
|
794
|
+
priority = 1000,
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
"LazyVim/LazyVim",
|
|
798
|
+
opts = {
|
|
799
|
+
colorscheme = "example-theme",
|
|
800
|
+
},
|
|
801
|
+
},
|
|
802
|
+
}
|
|
803
|
+
`;
|
|
804
|
+
var EXAMPLE_GHOSTTY_CONF = `# Ghostty terminal theme
|
|
805
|
+
# Add your terminal colors here
|
|
806
|
+
theme = example-theme
|
|
807
|
+
`;
|
|
808
|
+
var THEME_README = `# Example Theme
|
|
809
|
+
|
|
810
|
+
This is a template theme for FormalConf.
|
|
811
|
+
|
|
812
|
+
## Structure
|
|
813
|
+
- \`theme.yaml\` - Theme metadata and color definitions
|
|
814
|
+
- \`neovim.lua\` - Neovim colorscheme config
|
|
815
|
+
- \`ghostty.conf\` - Ghostty terminal theme
|
|
816
|
+
- \`backgrounds/\` - Wallpaper images (optional)
|
|
817
|
+
|
|
818
|
+
## Creating Your Own Theme
|
|
819
|
+
1. Copy this directory and rename it
|
|
820
|
+
2. Update \`theme.yaml\` with your theme info
|
|
821
|
+
3. Add config files for your applications
|
|
822
|
+
4. Files are symlinked to ~/.config/formalconf/current/theme/
|
|
823
|
+
`;
|
|
824
|
+
var BACKGROUNDS_README = `# Backgrounds
|
|
825
|
+
|
|
826
|
+
Place wallpaper images here:
|
|
827
|
+
- Supported formats: PNG, JPG
|
|
828
|
+
- These will be available at ~/.config/formalconf/current/backgrounds/
|
|
829
|
+
`;
|
|
830
|
+
var CONFIGS_README = `# Configs Directory
|
|
831
|
+
|
|
832
|
+
This directory contains your stow packages - collections of dotfiles
|
|
833
|
+
that are symlinked to your home directory.
|
|
834
|
+
|
|
835
|
+
## Creating a Config Package
|
|
836
|
+
|
|
837
|
+
1. Create a new directory: \`mkdir my-app\`
|
|
838
|
+
2. Add files mirroring your home directory structure
|
|
839
|
+
3. Use FormalConf to stow the package
|
|
840
|
+
|
|
841
|
+
## Example Structure
|
|
842
|
+
\`\`\`
|
|
843
|
+
my-app/
|
|
844
|
+
.config/
|
|
845
|
+
my-app/
|
|
846
|
+
config.toml -> ~/.config/my-app/config.toml
|
|
847
|
+
.my-app-rc -> ~/.my-app-rc
|
|
848
|
+
\`\`\`
|
|
849
|
+
|
|
850
|
+
## Commands
|
|
851
|
+
- Stow: Creates symlinks from home directory to these files
|
|
852
|
+
- Unstow: Removes the symlinks
|
|
853
|
+
- Status: Shows which packages are stowed
|
|
854
|
+
`;
|
|
855
|
+
var THEMES_README = `# Themes Directory
|
|
856
|
+
|
|
857
|
+
Themes contain application-specific config files that define colors and styling.
|
|
858
|
+
|
|
859
|
+
## Theme Structure
|
|
860
|
+
\`\`\`
|
|
861
|
+
my-theme/
|
|
862
|
+
theme.yaml # Theme metadata (required)
|
|
863
|
+
neovim.lua # Neovim colorscheme
|
|
864
|
+
ghostty.conf # Terminal theme
|
|
865
|
+
backgrounds/ # Wallpaper images
|
|
866
|
+
\`\`\`
|
|
867
|
+
|
|
868
|
+
## Applying Themes
|
|
869
|
+
Select a theme in FormalConf to symlink its files to:
|
|
870
|
+
\`~/.config/formalconf/current/theme/\`
|
|
871
|
+
|
|
872
|
+
Your applications should source files from this location.
|
|
873
|
+
`;
|
|
874
|
+
async function installExampleConfig() {
|
|
875
|
+
const dest = join3(CONFIGS_DIR, "example-config");
|
|
876
|
+
if (existsSync2(dest))
|
|
877
|
+
return;
|
|
878
|
+
await ensureDir2(dest);
|
|
879
|
+
await ensureDir2(join3(dest, ".config", "example-app"));
|
|
880
|
+
await writeFile(join3(dest, "README.md"), EXAMPLE_CONFIG_README);
|
|
881
|
+
await writeFile(join3(dest, ".config", "example-app", "config.toml"), EXAMPLE_CONFIG_TOML);
|
|
882
|
+
await writeFile(join3(dest, ".example-app-rc"), EXAMPLE_RC);
|
|
883
|
+
}
|
|
884
|
+
async function installExampleTheme() {
|
|
885
|
+
const dest = join3(THEMES_DIR, "example-theme");
|
|
886
|
+
if (existsSync2(dest))
|
|
887
|
+
return;
|
|
888
|
+
await ensureDir2(dest);
|
|
889
|
+
await ensureDir2(join3(dest, "backgrounds"));
|
|
890
|
+
await writeFile(join3(dest, "theme.yaml"), EXAMPLE_THEME_YAML);
|
|
891
|
+
await writeFile(join3(dest, "neovim.lua"), EXAMPLE_NEOVIM_LUA);
|
|
892
|
+
await writeFile(join3(dest, "ghostty.conf"), EXAMPLE_GHOSTTY_CONF);
|
|
893
|
+
await writeFile(join3(dest, "backgrounds", "README.md"), BACKGROUNDS_README);
|
|
894
|
+
await writeFile(join3(dest, "README.md"), THEME_README);
|
|
895
|
+
}
|
|
896
|
+
async function installReadmes() {
|
|
897
|
+
const configsReadme = join3(CONFIGS_DIR, "README.md");
|
|
898
|
+
const themesReadme = join3(THEMES_DIR, "README.md");
|
|
899
|
+
if (!existsSync2(configsReadme)) {
|
|
900
|
+
await writeFile(configsReadme, CONFIGS_README);
|
|
901
|
+
}
|
|
902
|
+
if (!existsSync2(themesReadme)) {
|
|
903
|
+
await writeFile(themesReadme, THEMES_README);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
var DEFAULT_PKG_CONFIG = {
|
|
907
|
+
config: {
|
|
908
|
+
purge: false,
|
|
909
|
+
purgeInteractive: true,
|
|
910
|
+
autoUpdate: true
|
|
911
|
+
},
|
|
912
|
+
taps: [],
|
|
913
|
+
packages: [],
|
|
914
|
+
casks: [],
|
|
915
|
+
mas: {}
|
|
916
|
+
};
|
|
917
|
+
async function installPkgConfig() {
|
|
918
|
+
if (existsSync2(PKG_CONFIG_PATH))
|
|
919
|
+
return;
|
|
920
|
+
await writeFile(PKG_CONFIG_PATH, JSON.stringify(DEFAULT_PKG_CONFIG, null, 2));
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
// src/components/Onboarding.tsx
|
|
725
924
|
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
925
|
+
function Onboarding({ onComplete }) {
|
|
926
|
+
const [step, setStep] = useState4("welcome");
|
|
927
|
+
const [createdItems, setCreatedItems] = useState4([]);
|
|
928
|
+
const addCreatedItem = (item) => {
|
|
929
|
+
setCreatedItems((prev) => [...prev, item]);
|
|
930
|
+
};
|
|
931
|
+
switch (step) {
|
|
932
|
+
case "welcome":
|
|
933
|
+
return /* @__PURE__ */ jsxDEV9(WelcomeStep, {
|
|
934
|
+
onNext: () => setStep("configs")
|
|
935
|
+
}, undefined, false, undefined, this);
|
|
936
|
+
case "configs":
|
|
937
|
+
return /* @__PURE__ */ jsxDEV9(ConfigsStep, {
|
|
938
|
+
onNext: () => setStep("themes"),
|
|
939
|
+
onCreate: async () => {
|
|
940
|
+
await installExampleConfig();
|
|
941
|
+
addCreatedItem("Example config package");
|
|
942
|
+
}
|
|
943
|
+
}, undefined, false, undefined, this);
|
|
944
|
+
case "themes":
|
|
945
|
+
return /* @__PURE__ */ jsxDEV9(ThemesStep, {
|
|
946
|
+
onNext: () => setStep("packages"),
|
|
947
|
+
onCreate: async () => {
|
|
948
|
+
await installExampleTheme();
|
|
949
|
+
addCreatedItem("Example theme");
|
|
950
|
+
}
|
|
951
|
+
}, undefined, false, undefined, this);
|
|
952
|
+
case "packages":
|
|
953
|
+
return /* @__PURE__ */ jsxDEV9(PackagesStep, {
|
|
954
|
+
onNext: async () => {
|
|
955
|
+
await installPkgConfig();
|
|
956
|
+
setStep("complete");
|
|
957
|
+
}
|
|
958
|
+
}, undefined, false, undefined, this);
|
|
959
|
+
case "complete":
|
|
960
|
+
return /* @__PURE__ */ jsxDEV9(CompleteStep, {
|
|
961
|
+
createdItems,
|
|
962
|
+
onComplete: async () => {
|
|
963
|
+
await installReadmes();
|
|
964
|
+
onComplete();
|
|
965
|
+
}
|
|
966
|
+
}, undefined, false, undefined, this);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
function WelcomeStep({ onNext }) {
|
|
970
|
+
useInput3((_, key) => {
|
|
971
|
+
if (key.return)
|
|
972
|
+
onNext();
|
|
973
|
+
});
|
|
974
|
+
return /* @__PURE__ */ jsxDEV9(Layout, {
|
|
975
|
+
breadcrumb: ["Setup"],
|
|
976
|
+
showFooter: false,
|
|
977
|
+
children: /* @__PURE__ */ jsxDEV9(Panel, {
|
|
978
|
+
title: "Welcome to FormalConf",
|
|
979
|
+
children: /* @__PURE__ */ jsxDEV9(Box9, {
|
|
980
|
+
flexDirection: "column",
|
|
981
|
+
gap: 1,
|
|
982
|
+
children: [
|
|
983
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
984
|
+
children: "FormalConf helps you manage your dotfiles and system configuration."
|
|
985
|
+
}, undefined, false, undefined, this),
|
|
986
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
987
|
+
dimColor: true,
|
|
988
|
+
children: "This setup will walk you through the basics and optionally create example files to get you started."
|
|
989
|
+
}, undefined, false, undefined, this),
|
|
990
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
991
|
+
marginTop: 1,
|
|
992
|
+
children: /* @__PURE__ */ jsxDEV9(Text8, {
|
|
993
|
+
color: colors.primary,
|
|
994
|
+
children: "Press Enter to continue..."
|
|
995
|
+
}, undefined, false, undefined, this)
|
|
996
|
+
}, undefined, false, undefined, this)
|
|
997
|
+
]
|
|
998
|
+
}, undefined, true, undefined, this)
|
|
999
|
+
}, undefined, false, undefined, this)
|
|
1000
|
+
}, undefined, false, undefined, this);
|
|
1001
|
+
}
|
|
1002
|
+
function ConfigsStep({
|
|
1003
|
+
onNext,
|
|
1004
|
+
onCreate
|
|
1005
|
+
}) {
|
|
1006
|
+
const [isCreating, setIsCreating] = useState4(false);
|
|
1007
|
+
const handleSelect = async (value) => {
|
|
1008
|
+
if (value === "create") {
|
|
1009
|
+
setIsCreating(true);
|
|
1010
|
+
await onCreate();
|
|
1011
|
+
}
|
|
1012
|
+
onNext();
|
|
1013
|
+
};
|
|
1014
|
+
return /* @__PURE__ */ jsxDEV9(Layout, {
|
|
1015
|
+
breadcrumb: ["Setup", "Config Packages"],
|
|
1016
|
+
showFooter: false,
|
|
1017
|
+
children: /* @__PURE__ */ jsxDEV9(Panel, {
|
|
1018
|
+
title: "Config Packages",
|
|
1019
|
+
children: /* @__PURE__ */ jsxDEV9(Box9, {
|
|
1020
|
+
flexDirection: "column",
|
|
1021
|
+
gap: 1,
|
|
1022
|
+
children: [
|
|
1023
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1024
|
+
children: "Config packages are directories containing your dotfiles."
|
|
1025
|
+
}, undefined, false, undefined, this),
|
|
1026
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1027
|
+
dimColor: true,
|
|
1028
|
+
children: "FormalConf uses GNU Stow to create symlinks from your home directory."
|
|
1029
|
+
}, undefined, false, undefined, this),
|
|
1030
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
1031
|
+
marginTop: 1,
|
|
1032
|
+
flexDirection: "column",
|
|
1033
|
+
children: [
|
|
1034
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1035
|
+
dimColor: true,
|
|
1036
|
+
children: "Example structure:"
|
|
1037
|
+
}, undefined, false, undefined, this),
|
|
1038
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1039
|
+
children: " my-config/"
|
|
1040
|
+
}, undefined, false, undefined, this),
|
|
1041
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1042
|
+
children: " .config/"
|
|
1043
|
+
}, undefined, false, undefined, this),
|
|
1044
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1045
|
+
children: " app/config.toml"
|
|
1046
|
+
}, undefined, false, undefined, this)
|
|
1047
|
+
]
|
|
1048
|
+
}, undefined, true, undefined, this),
|
|
1049
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
1050
|
+
marginTop: 1,
|
|
1051
|
+
children: /* @__PURE__ */ jsxDEV9(VimSelect, {
|
|
1052
|
+
options: [
|
|
1053
|
+
{ label: "Create example config package", value: "create" },
|
|
1054
|
+
{ label: "Skip", value: "skip" }
|
|
1055
|
+
],
|
|
1056
|
+
onChange: handleSelect,
|
|
1057
|
+
isDisabled: isCreating
|
|
1058
|
+
}, undefined, false, undefined, this)
|
|
1059
|
+
}, undefined, false, undefined, this)
|
|
1060
|
+
]
|
|
1061
|
+
}, undefined, true, undefined, this)
|
|
1062
|
+
}, undefined, false, undefined, this)
|
|
1063
|
+
}, undefined, false, undefined, this);
|
|
1064
|
+
}
|
|
1065
|
+
function ThemesStep({
|
|
1066
|
+
onNext,
|
|
1067
|
+
onCreate
|
|
1068
|
+
}) {
|
|
1069
|
+
const [isCreating, setIsCreating] = useState4(false);
|
|
1070
|
+
const handleSelect = async (value) => {
|
|
1071
|
+
if (value === "create") {
|
|
1072
|
+
setIsCreating(true);
|
|
1073
|
+
await onCreate();
|
|
1074
|
+
}
|
|
1075
|
+
onNext();
|
|
1076
|
+
};
|
|
1077
|
+
return /* @__PURE__ */ jsxDEV9(Layout, {
|
|
1078
|
+
breadcrumb: ["Setup", "Themes"],
|
|
1079
|
+
showFooter: false,
|
|
1080
|
+
children: /* @__PURE__ */ jsxDEV9(Panel, {
|
|
1081
|
+
title: "Themes",
|
|
1082
|
+
children: /* @__PURE__ */ jsxDEV9(Box9, {
|
|
1083
|
+
flexDirection: "column",
|
|
1084
|
+
gap: 1,
|
|
1085
|
+
children: [
|
|
1086
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1087
|
+
children: "Themes contain application configs for colors and styling."
|
|
1088
|
+
}, undefined, false, undefined, this),
|
|
1089
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1090
|
+
dimColor: true,
|
|
1091
|
+
children: "When applied, theme files are symlinked to a central location your apps can source from."
|
|
1092
|
+
}, undefined, false, undefined, this),
|
|
1093
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
1094
|
+
marginTop: 1,
|
|
1095
|
+
flexDirection: "column",
|
|
1096
|
+
children: [
|
|
1097
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1098
|
+
dimColor: true,
|
|
1099
|
+
children: "Theme structure:"
|
|
1100
|
+
}, undefined, false, undefined, this),
|
|
1101
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1102
|
+
children: " my-theme/"
|
|
1103
|
+
}, undefined, false, undefined, this),
|
|
1104
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1105
|
+
children: " theme.yaml"
|
|
1106
|
+
}, undefined, false, undefined, this),
|
|
1107
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1108
|
+
children: " neovim.lua"
|
|
1109
|
+
}, undefined, false, undefined, this),
|
|
1110
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1111
|
+
children: " backgrounds/"
|
|
1112
|
+
}, undefined, false, undefined, this)
|
|
1113
|
+
]
|
|
1114
|
+
}, undefined, true, undefined, this),
|
|
1115
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
1116
|
+
marginTop: 1,
|
|
1117
|
+
children: /* @__PURE__ */ jsxDEV9(VimSelect, {
|
|
1118
|
+
options: [
|
|
1119
|
+
{ label: "Create example theme", value: "create" },
|
|
1120
|
+
{ label: "Skip", value: "skip" }
|
|
1121
|
+
],
|
|
1122
|
+
onChange: handleSelect,
|
|
1123
|
+
isDisabled: isCreating
|
|
1124
|
+
}, undefined, false, undefined, this)
|
|
1125
|
+
}, undefined, false, undefined, this)
|
|
1126
|
+
]
|
|
1127
|
+
}, undefined, true, undefined, this)
|
|
1128
|
+
}, undefined, false, undefined, this)
|
|
1129
|
+
}, undefined, false, undefined, this);
|
|
1130
|
+
}
|
|
1131
|
+
function PackagesStep({ onNext }) {
|
|
1132
|
+
const [isCreating, setIsCreating] = useState4(false);
|
|
1133
|
+
useInput3(async (_, key) => {
|
|
1134
|
+
if (key.return && !isCreating) {
|
|
1135
|
+
setIsCreating(true);
|
|
1136
|
+
await onNext();
|
|
1137
|
+
}
|
|
1138
|
+
});
|
|
1139
|
+
return /* @__PURE__ */ jsxDEV9(Layout, {
|
|
1140
|
+
breadcrumb: ["Setup", "Package Sync"],
|
|
1141
|
+
showFooter: false,
|
|
1142
|
+
children: /* @__PURE__ */ jsxDEV9(Panel, {
|
|
1143
|
+
title: "Package Sync",
|
|
1144
|
+
children: /* @__PURE__ */ jsxDEV9(Box9, {
|
|
1145
|
+
flexDirection: "column",
|
|
1146
|
+
gap: 1,
|
|
1147
|
+
children: [
|
|
1148
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1149
|
+
children: "FormalConf can sync your Homebrew packages from a config file."
|
|
1150
|
+
}, undefined, false, undefined, this),
|
|
1151
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1152
|
+
dimColor: true,
|
|
1153
|
+
children: "Edit ~/.config/formalconf/pkg-config.json to define your packages, then run Package Sync from the main menu."
|
|
1154
|
+
}, undefined, false, undefined, this),
|
|
1155
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
1156
|
+
marginTop: 1,
|
|
1157
|
+
children: /* @__PURE__ */ jsxDEV9(Text8, {
|
|
1158
|
+
color: colors.primary,
|
|
1159
|
+
children: "Press Enter to continue..."
|
|
1160
|
+
}, undefined, false, undefined, this)
|
|
1161
|
+
}, undefined, false, undefined, this)
|
|
1162
|
+
]
|
|
1163
|
+
}, undefined, true, undefined, this)
|
|
1164
|
+
}, undefined, false, undefined, this)
|
|
1165
|
+
}, undefined, false, undefined, this);
|
|
1166
|
+
}
|
|
1167
|
+
function CompleteStep({
|
|
1168
|
+
createdItems,
|
|
1169
|
+
onComplete
|
|
1170
|
+
}) {
|
|
1171
|
+
const [isFinishing, setIsFinishing] = useState4(false);
|
|
1172
|
+
useInput3(async (_, key) => {
|
|
1173
|
+
if (key.return && !isFinishing) {
|
|
1174
|
+
setIsFinishing(true);
|
|
1175
|
+
await onComplete();
|
|
1176
|
+
}
|
|
1177
|
+
});
|
|
1178
|
+
return /* @__PURE__ */ jsxDEV9(Layout, {
|
|
1179
|
+
breadcrumb: ["Setup", "Complete"],
|
|
1180
|
+
showFooter: false,
|
|
1181
|
+
children: /* @__PURE__ */ jsxDEV9(Panel, {
|
|
1182
|
+
title: "Setup Complete",
|
|
1183
|
+
children: /* @__PURE__ */ jsxDEV9(Box9, {
|
|
1184
|
+
flexDirection: "column",
|
|
1185
|
+
gap: 1,
|
|
1186
|
+
children: [
|
|
1187
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1188
|
+
color: colors.success,
|
|
1189
|
+
children: "You're all set!"
|
|
1190
|
+
}, undefined, false, undefined, this),
|
|
1191
|
+
createdItems.length > 0 && /* @__PURE__ */ jsxDEV9(Box9, {
|
|
1192
|
+
flexDirection: "column",
|
|
1193
|
+
marginTop: 1,
|
|
1194
|
+
children: [
|
|
1195
|
+
/* @__PURE__ */ jsxDEV9(Text8, {
|
|
1196
|
+
dimColor: true,
|
|
1197
|
+
children: "Created:"
|
|
1198
|
+
}, undefined, false, undefined, this),
|
|
1199
|
+
createdItems.map((item, i) => /* @__PURE__ */ jsxDEV9(Text8, {
|
|
1200
|
+
children: [
|
|
1201
|
+
" - ",
|
|
1202
|
+
item
|
|
1203
|
+
]
|
|
1204
|
+
}, i, true, undefined, this))
|
|
1205
|
+
]
|
|
1206
|
+
}, undefined, true, undefined, this),
|
|
1207
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
1208
|
+
marginTop: 1,
|
|
1209
|
+
children: /* @__PURE__ */ jsxDEV9(Text8, {
|
|
1210
|
+
dimColor: true,
|
|
1211
|
+
children: "README files have been added to help you get started."
|
|
1212
|
+
}, undefined, false, undefined, this)
|
|
1213
|
+
}, undefined, false, undefined, this),
|
|
1214
|
+
/* @__PURE__ */ jsxDEV9(Box9, {
|
|
1215
|
+
marginTop: 1,
|
|
1216
|
+
children: /* @__PURE__ */ jsxDEV9(Text8, {
|
|
1217
|
+
color: colors.primary,
|
|
1218
|
+
children: "Press Enter to start..."
|
|
1219
|
+
}, undefined, false, undefined, this)
|
|
1220
|
+
}, undefined, false, undefined, this)
|
|
1221
|
+
]
|
|
1222
|
+
}, undefined, true, undefined, this)
|
|
1223
|
+
}, undefined, false, undefined, this)
|
|
1224
|
+
}, undefined, false, undefined, this);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// src/components/menus/MainMenu.tsx
|
|
1228
|
+
import { useApp } from "ink";
|
|
1229
|
+
import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
|
|
726
1230
|
function MainMenu({ onSelect }) {
|
|
727
1231
|
const { exit } = useApp();
|
|
728
|
-
return /* @__PURE__ */
|
|
1232
|
+
return /* @__PURE__ */ jsxDEV10(Panel, {
|
|
729
1233
|
title: "Main Menu",
|
|
730
|
-
children: /* @__PURE__ */
|
|
1234
|
+
children: /* @__PURE__ */ jsxDEV10(VimSelect, {
|
|
731
1235
|
options: [
|
|
732
1236
|
{ label: "Config Manager", value: "config" },
|
|
733
1237
|
{ label: "Package Sync", value: "packages" },
|
|
@@ -746,33 +1250,33 @@ function MainMenu({ onSelect }) {
|
|
|
746
1250
|
}
|
|
747
1251
|
|
|
748
1252
|
// src/components/CommandOutput.tsx
|
|
749
|
-
import { Box as
|
|
750
|
-
import { jsxDEV as
|
|
1253
|
+
import { Box as Box10, Text as Text9, useInput as useInput4 } from "ink";
|
|
1254
|
+
import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
|
|
751
1255
|
function CommandOutput({
|
|
752
1256
|
title,
|
|
753
1257
|
output,
|
|
754
1258
|
success = true,
|
|
755
1259
|
onDismiss
|
|
756
1260
|
}) {
|
|
757
|
-
|
|
1261
|
+
useInput4(() => {
|
|
758
1262
|
onDismiss();
|
|
759
1263
|
});
|
|
760
|
-
return /* @__PURE__ */
|
|
1264
|
+
return /* @__PURE__ */ jsxDEV11(Panel, {
|
|
761
1265
|
title,
|
|
762
1266
|
borderColor: success ? colors.success : colors.error,
|
|
763
1267
|
children: [
|
|
764
|
-
output && /* @__PURE__ */
|
|
1268
|
+
output && /* @__PURE__ */ jsxDEV11(Box10, {
|
|
765
1269
|
flexDirection: "column",
|
|
766
1270
|
marginBottom: 1,
|
|
767
|
-
children: /* @__PURE__ */
|
|
1271
|
+
children: /* @__PURE__ */ jsxDEV11(Text9, {
|
|
768
1272
|
children: output
|
|
769
1273
|
}, undefined, false, undefined, this)
|
|
770
1274
|
}, undefined, false, undefined, this),
|
|
771
|
-
/* @__PURE__ */
|
|
1275
|
+
/* @__PURE__ */ jsxDEV11(Text9, {
|
|
772
1276
|
color: success ? colors.success : colors.error,
|
|
773
1277
|
children: success ? "Done" : "Failed"
|
|
774
1278
|
}, undefined, false, undefined, this),
|
|
775
|
-
/* @__PURE__ */
|
|
1279
|
+
/* @__PURE__ */ jsxDEV11(Text9, {
|
|
776
1280
|
dimColor: true,
|
|
777
1281
|
children: "Press any key to continue..."
|
|
778
1282
|
}, undefined, false, undefined, this)
|
|
@@ -782,22 +1286,22 @@ function CommandOutput({
|
|
|
782
1286
|
|
|
783
1287
|
// src/components/LoadingPanel.tsx
|
|
784
1288
|
import { Spinner } from "@inkjs/ui";
|
|
785
|
-
import { jsxDEV as
|
|
1289
|
+
import { jsxDEV as jsxDEV12 } from "react/jsx-dev-runtime";
|
|
786
1290
|
function LoadingPanel({ title, label = "Processing..." }) {
|
|
787
|
-
return /* @__PURE__ */
|
|
1291
|
+
return /* @__PURE__ */ jsxDEV12(Panel, {
|
|
788
1292
|
title,
|
|
789
|
-
children: /* @__PURE__ */
|
|
1293
|
+
children: /* @__PURE__ */ jsxDEV12(Spinner, {
|
|
790
1294
|
label
|
|
791
1295
|
}, undefined, false, undefined, this)
|
|
792
1296
|
}, undefined, false, undefined, this);
|
|
793
1297
|
}
|
|
794
1298
|
|
|
795
1299
|
// src/hooks/useMenuAction.ts
|
|
796
|
-
import { useState as
|
|
1300
|
+
import { useState as useState5, useCallback } from "react";
|
|
797
1301
|
function useMenuAction() {
|
|
798
|
-
const [state, setState] =
|
|
799
|
-
const [output, setOutput] =
|
|
800
|
-
const [success, setSuccess] =
|
|
1302
|
+
const [state, setState] = useState5("menu");
|
|
1303
|
+
const [output, setOutput] = useState5("");
|
|
1304
|
+
const [success, setSuccess] = useState5(true);
|
|
801
1305
|
const execute = useCallback(async (action) => {
|
|
802
1306
|
setState("running");
|
|
803
1307
|
const result = await action();
|
|
@@ -820,12 +1324,12 @@ function useMenuAction() {
|
|
|
820
1324
|
}
|
|
821
1325
|
|
|
822
1326
|
// src/hooks/useBackNavigation.ts
|
|
823
|
-
import { useInput as
|
|
1327
|
+
import { useInput as useInput5 } from "ink";
|
|
824
1328
|
function useBackNavigation({
|
|
825
1329
|
enabled = true,
|
|
826
1330
|
onBack
|
|
827
1331
|
}) {
|
|
828
|
-
|
|
1332
|
+
useInput5((input, key) => {
|
|
829
1333
|
if (enabled && (key.escape || key.leftArrow || input === "h")) {
|
|
830
1334
|
onBack();
|
|
831
1335
|
}
|
|
@@ -834,7 +1338,7 @@ function useBackNavigation({
|
|
|
834
1338
|
|
|
835
1339
|
// src/cli/config-manager.ts
|
|
836
1340
|
import { parseArgs } from "util";
|
|
837
|
-
import { readdirSync as readdirSync2, existsSync as
|
|
1341
|
+
import { readdirSync as readdirSync2, existsSync as existsSync3, lstatSync as lstatSync2, readlinkSync as readlinkSync2 } from "fs";
|
|
838
1342
|
var colors2 = {
|
|
839
1343
|
red: "\x1B[0;31m",
|
|
840
1344
|
green: "\x1B[0;32m",
|
|
@@ -859,12 +1363,12 @@ function listPackages() {
|
|
|
859
1363
|
}
|
|
860
1364
|
function checkPackageStowed(packageName) {
|
|
861
1365
|
const packageDir = `${CONFIGS_DIR}/${packageName}`;
|
|
862
|
-
if (!
|
|
1366
|
+
if (!existsSync3(packageDir))
|
|
863
1367
|
return false;
|
|
864
1368
|
const entries = readdirSync2(packageDir, { withFileTypes: true });
|
|
865
1369
|
for (const entry of entries) {
|
|
866
1370
|
const targetPath = `${HOME_DIR}/${entry.name}`;
|
|
867
|
-
if (!
|
|
1371
|
+
if (!existsSync3(targetPath))
|
|
868
1372
|
return false;
|
|
869
1373
|
try {
|
|
870
1374
|
const stat = lstatSync2(targetPath);
|
|
@@ -1130,7 +1634,7 @@ if (isMainModule) {
|
|
|
1130
1634
|
}
|
|
1131
1635
|
|
|
1132
1636
|
// src/components/menus/ConfigMenu.tsx
|
|
1133
|
-
import { jsxDEV as
|
|
1637
|
+
import { jsxDEV as jsxDEV13 } from "react/jsx-dev-runtime";
|
|
1134
1638
|
function ConfigMenu({ onBack }) {
|
|
1135
1639
|
const { state, output, success, isRunning, isResult, execute, reset } = useMenuAction();
|
|
1136
1640
|
useBackNavigation({ enabled: state === "menu", onBack });
|
|
@@ -1142,21 +1646,21 @@ function ConfigMenu({ onBack }) {
|
|
|
1142
1646
|
await execute(() => runConfigManager([action]));
|
|
1143
1647
|
};
|
|
1144
1648
|
if (isRunning) {
|
|
1145
|
-
return /* @__PURE__ */
|
|
1649
|
+
return /* @__PURE__ */ jsxDEV13(LoadingPanel, {
|
|
1146
1650
|
title: "Config Manager"
|
|
1147
1651
|
}, undefined, false, undefined, this);
|
|
1148
1652
|
}
|
|
1149
1653
|
if (isResult) {
|
|
1150
|
-
return /* @__PURE__ */
|
|
1654
|
+
return /* @__PURE__ */ jsxDEV13(CommandOutput, {
|
|
1151
1655
|
title: "Config Manager",
|
|
1152
1656
|
output,
|
|
1153
1657
|
success,
|
|
1154
1658
|
onDismiss: reset
|
|
1155
1659
|
}, undefined, false, undefined, this);
|
|
1156
1660
|
}
|
|
1157
|
-
return /* @__PURE__ */
|
|
1661
|
+
return /* @__PURE__ */ jsxDEV13(Panel, {
|
|
1158
1662
|
title: "Config Manager",
|
|
1159
|
-
children: /* @__PURE__ */
|
|
1663
|
+
children: /* @__PURE__ */ jsxDEV13(VimSelect, {
|
|
1160
1664
|
options: [
|
|
1161
1665
|
{ label: "Stow all packages", value: "stow-all" },
|
|
1162
1666
|
{ label: "Unstow all packages", value: "unstow-all" },
|
|
@@ -1170,13 +1674,13 @@ function ConfigMenu({ onBack }) {
|
|
|
1170
1674
|
}
|
|
1171
1675
|
|
|
1172
1676
|
// src/components/menus/PackageMenu.tsx
|
|
1173
|
-
import { useState as
|
|
1174
|
-
import { Box as
|
|
1677
|
+
import { useState as useState7, useCallback as useCallback2, useMemo as useMemo2, useRef } from "react";
|
|
1678
|
+
import { Box as Box13, Text as Text12, useInput as useInput8 } from "ink";
|
|
1175
1679
|
|
|
1176
1680
|
// src/components/ScrollableLog.tsx
|
|
1177
|
-
import { useState as
|
|
1178
|
-
import { Box as
|
|
1179
|
-
import { jsxDEV as
|
|
1681
|
+
import { useState as useState6, useEffect as useEffect3, useMemo } from "react";
|
|
1682
|
+
import { Box as Box11, Text as Text10, useInput as useInput6 } from "ink";
|
|
1683
|
+
import { jsxDEV as jsxDEV14 } from "react/jsx-dev-runtime";
|
|
1180
1684
|
function ScrollableLog({
|
|
1181
1685
|
lines,
|
|
1182
1686
|
maxHeight,
|
|
@@ -1185,8 +1689,8 @@ function ScrollableLog({
|
|
|
1185
1689
|
}) {
|
|
1186
1690
|
const { rows } = useTerminalSize();
|
|
1187
1691
|
const visibleLines = maxHeight || Math.max(5, rows - 12);
|
|
1188
|
-
const [scrollOffset, setScrollOffset] =
|
|
1189
|
-
const [isAutoScrolling, setIsAutoScrolling] =
|
|
1692
|
+
const [scrollOffset, setScrollOffset] = useState6(0);
|
|
1693
|
+
const [isAutoScrolling, setIsAutoScrolling] = useState6(autoScroll);
|
|
1190
1694
|
const totalLines = lines.length;
|
|
1191
1695
|
const maxOffset = Math.max(0, totalLines - visibleLines);
|
|
1192
1696
|
useEffect3(() => {
|
|
@@ -1194,7 +1698,7 @@ function ScrollableLog({
|
|
|
1194
1698
|
setScrollOffset(maxOffset);
|
|
1195
1699
|
}
|
|
1196
1700
|
}, [totalLines, maxOffset, isAutoScrolling]);
|
|
1197
|
-
|
|
1701
|
+
useInput6((input, key) => {
|
|
1198
1702
|
if (key.downArrow || input === "j") {
|
|
1199
1703
|
setIsAutoScrolling(false);
|
|
1200
1704
|
setScrollOffset((prev) => Math.min(prev + 1, maxOffset));
|
|
@@ -1217,10 +1721,10 @@ function ScrollableLog({
|
|
|
1217
1721
|
}, [lines, scrollOffset, visibleLines]);
|
|
1218
1722
|
const showScrollUp = scrollOffset > 0;
|
|
1219
1723
|
const showScrollDown = scrollOffset < maxOffset;
|
|
1220
|
-
return /* @__PURE__ */
|
|
1724
|
+
return /* @__PURE__ */ jsxDEV14(Box11, {
|
|
1221
1725
|
flexDirection: "column",
|
|
1222
1726
|
children: [
|
|
1223
|
-
showScrollHint && showScrollUp && /* @__PURE__ */
|
|
1727
|
+
showScrollHint && showScrollUp && /* @__PURE__ */ jsxDEV14(Text10, {
|
|
1224
1728
|
dimColor: true,
|
|
1225
1729
|
children: [
|
|
1226
1730
|
" ↑ ",
|
|
@@ -1229,15 +1733,15 @@ function ScrollableLog({
|
|
|
1229
1733
|
scrollOffset !== 1 ? "s" : ""
|
|
1230
1734
|
]
|
|
1231
1735
|
}, undefined, true, undefined, this),
|
|
1232
|
-
/* @__PURE__ */
|
|
1736
|
+
/* @__PURE__ */ jsxDEV14(Box11, {
|
|
1233
1737
|
flexDirection: "column",
|
|
1234
1738
|
height: visibleLines,
|
|
1235
1739
|
overflow: "hidden",
|
|
1236
|
-
children: visibleContent.map((line, i) => /* @__PURE__ */
|
|
1740
|
+
children: visibleContent.map((line, i) => /* @__PURE__ */ jsxDEV14(Text10, {
|
|
1237
1741
|
children: line
|
|
1238
1742
|
}, scrollOffset + i, false, undefined, this))
|
|
1239
1743
|
}, undefined, false, undefined, this),
|
|
1240
|
-
showScrollHint && showScrollDown && /* @__PURE__ */
|
|
1744
|
+
showScrollHint && showScrollDown && /* @__PURE__ */ jsxDEV14(Text10, {
|
|
1241
1745
|
dimColor: true,
|
|
1242
1746
|
children: [
|
|
1243
1747
|
" ↓ ",
|
|
@@ -1246,7 +1750,7 @@ function ScrollableLog({
|
|
|
1246
1750
|
maxOffset - scrollOffset !== 1 ? "s" : ""
|
|
1247
1751
|
]
|
|
1248
1752
|
}, undefined, true, undefined, this),
|
|
1249
|
-
showScrollHint && totalLines > visibleLines && /* @__PURE__ */
|
|
1753
|
+
showScrollHint && totalLines > visibleLines && /* @__PURE__ */ jsxDEV14(Text10, {
|
|
1250
1754
|
dimColor: true,
|
|
1251
1755
|
children: [
|
|
1252
1756
|
"j/k scroll • g top • G bottom ",
|
|
@@ -1258,29 +1762,29 @@ function ScrollableLog({
|
|
|
1258
1762
|
}
|
|
1259
1763
|
|
|
1260
1764
|
// src/components/PromptInput.tsx
|
|
1261
|
-
import { Box as
|
|
1262
|
-
import { jsxDEV as
|
|
1765
|
+
import { Box as Box12, Text as Text11, useInput as useInput7 } from "ink";
|
|
1766
|
+
import { jsxDEV as jsxDEV15 } from "react/jsx-dev-runtime";
|
|
1263
1767
|
function PromptInput({
|
|
1264
1768
|
question,
|
|
1265
1769
|
options = ["y", "n"],
|
|
1266
1770
|
onAnswer
|
|
1267
1771
|
}) {
|
|
1268
|
-
|
|
1772
|
+
useInput7((input) => {
|
|
1269
1773
|
const lower = input.toLowerCase();
|
|
1270
1774
|
if (options.includes(lower)) {
|
|
1271
1775
|
onAnswer(lower);
|
|
1272
1776
|
}
|
|
1273
1777
|
});
|
|
1274
|
-
return /* @__PURE__ */
|
|
1778
|
+
return /* @__PURE__ */ jsxDEV15(Box12, {
|
|
1275
1779
|
marginTop: 1,
|
|
1276
1780
|
borderStyle: "single",
|
|
1277
1781
|
borderColor: colors.accent,
|
|
1278
1782
|
paddingX: 1,
|
|
1279
|
-
children: /* @__PURE__ */
|
|
1783
|
+
children: /* @__PURE__ */ jsxDEV15(Text11, {
|
|
1280
1784
|
children: [
|
|
1281
1785
|
question,
|
|
1282
1786
|
" ",
|
|
1283
|
-
/* @__PURE__ */
|
|
1787
|
+
/* @__PURE__ */ jsxDEV15(Text11, {
|
|
1284
1788
|
color: colors.accent,
|
|
1285
1789
|
children: [
|
|
1286
1790
|
"[",
|
|
@@ -1288,7 +1792,7 @@ function PromptInput({
|
|
|
1288
1792
|
"]"
|
|
1289
1793
|
]
|
|
1290
1794
|
}, undefined, true, undefined, this),
|
|
1291
|
-
/* @__PURE__ */
|
|
1795
|
+
/* @__PURE__ */ jsxDEV15(Text11, {
|
|
1292
1796
|
dimColor: true,
|
|
1293
1797
|
children: ": "
|
|
1294
1798
|
}, undefined, false, undefined, this)
|
|
@@ -1301,7 +1805,7 @@ function PromptInput({
|
|
|
1301
1805
|
import { parseArgs as parseArgs2 } from "util";
|
|
1302
1806
|
|
|
1303
1807
|
// src/lib/config.ts
|
|
1304
|
-
import { existsSync as
|
|
1808
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1305
1809
|
var DEFAULT_CONFIG = {
|
|
1306
1810
|
config: {
|
|
1307
1811
|
purge: false,
|
|
@@ -1316,7 +1820,7 @@ var DEFAULT_CONFIG = {
|
|
|
1316
1820
|
async function loadPkgConfig(path) {
|
|
1317
1821
|
await ensureConfigDir();
|
|
1318
1822
|
const configPath = path || PKG_CONFIG_PATH;
|
|
1319
|
-
if (!
|
|
1823
|
+
if (!existsSync4(configPath)) {
|
|
1320
1824
|
await savePkgConfig(DEFAULT_CONFIG, configPath);
|
|
1321
1825
|
return DEFAULT_CONFIG;
|
|
1322
1826
|
}
|
|
@@ -1328,7 +1832,7 @@ async function savePkgConfig(config, path) {
|
|
|
1328
1832
|
await writeFile(configPath, JSON.stringify(config, null, 2));
|
|
1329
1833
|
}
|
|
1330
1834
|
async function loadPkgLock() {
|
|
1331
|
-
if (!
|
|
1835
|
+
if (!existsSync4(PKG_LOCK_PATH)) {
|
|
1332
1836
|
return null;
|
|
1333
1837
|
}
|
|
1334
1838
|
return readJson(PKG_LOCK_PATH);
|
|
@@ -2110,16 +2614,16 @@ if (isMainModule3) {
|
|
|
2110
2614
|
}
|
|
2111
2615
|
|
|
2112
2616
|
// src/components/menus/PackageMenu.tsx
|
|
2113
|
-
import { jsxDEV as
|
|
2617
|
+
import { jsxDEV as jsxDEV16 } from "react/jsx-dev-runtime";
|
|
2114
2618
|
function PackageMenu({ onBack }) {
|
|
2115
|
-
const [state, setState] =
|
|
2116
|
-
const [lines, setLines] =
|
|
2117
|
-
const [output, setOutput] =
|
|
2118
|
-
const [isStreamingOp, setIsStreamingOp] =
|
|
2119
|
-
const [pendingPrompt, setPendingPrompt] =
|
|
2120
|
-
const [success, setSuccess] =
|
|
2619
|
+
const [state, setState] = useState7("menu");
|
|
2620
|
+
const [lines, setLines] = useState7([]);
|
|
2621
|
+
const [output, setOutput] = useState7("");
|
|
2622
|
+
const [isStreamingOp, setIsStreamingOp] = useState7(true);
|
|
2623
|
+
const [pendingPrompt, setPendingPrompt] = useState7(null);
|
|
2624
|
+
const [success, setSuccess] = useState7(true);
|
|
2121
2625
|
const isRunningRef = useRef(false);
|
|
2122
|
-
|
|
2626
|
+
useInput8((input, key) => {
|
|
2123
2627
|
if (state === "menu" && (key.escape || key.leftArrow || input === "h")) {
|
|
2124
2628
|
onBack();
|
|
2125
2629
|
}
|
|
@@ -2196,17 +2700,17 @@ function PackageMenu({ onBack }) {
|
|
|
2196
2700
|
};
|
|
2197
2701
|
if (state === "running") {
|
|
2198
2702
|
if (!isStreamingOp) {
|
|
2199
|
-
return /* @__PURE__ */
|
|
2703
|
+
return /* @__PURE__ */ jsxDEV16(LoadingPanel, {
|
|
2200
2704
|
title: "Package Sync"
|
|
2201
2705
|
}, undefined, false, undefined, this);
|
|
2202
2706
|
}
|
|
2203
|
-
return /* @__PURE__ */
|
|
2707
|
+
return /* @__PURE__ */ jsxDEV16(Panel, {
|
|
2204
2708
|
title: "Package Sync",
|
|
2205
2709
|
children: [
|
|
2206
|
-
/* @__PURE__ */
|
|
2710
|
+
/* @__PURE__ */ jsxDEV16(ScrollableLog, {
|
|
2207
2711
|
lines
|
|
2208
2712
|
}, undefined, false, undefined, this),
|
|
2209
|
-
pendingPrompt && /* @__PURE__ */
|
|
2713
|
+
pendingPrompt && /* @__PURE__ */ jsxDEV16(PromptInput, {
|
|
2210
2714
|
question: pendingPrompt.question,
|
|
2211
2715
|
options: pendingPrompt.options,
|
|
2212
2716
|
onAnswer: handlePromptAnswer
|
|
@@ -2216,38 +2720,38 @@ function PackageMenu({ onBack }) {
|
|
|
2216
2720
|
}
|
|
2217
2721
|
if (state === "result") {
|
|
2218
2722
|
if (!isStreamingOp) {
|
|
2219
|
-
return /* @__PURE__ */
|
|
2723
|
+
return /* @__PURE__ */ jsxDEV16(CommandOutput, {
|
|
2220
2724
|
title: "Package Sync",
|
|
2221
2725
|
output,
|
|
2222
2726
|
success,
|
|
2223
2727
|
onDismiss: () => setState("menu")
|
|
2224
2728
|
}, undefined, false, undefined, this);
|
|
2225
2729
|
}
|
|
2226
|
-
return /* @__PURE__ */
|
|
2730
|
+
return /* @__PURE__ */ jsxDEV16(Panel, {
|
|
2227
2731
|
title: "Package Sync",
|
|
2228
2732
|
borderColor: success ? colors.success : colors.error,
|
|
2229
2733
|
children: [
|
|
2230
|
-
/* @__PURE__ */
|
|
2734
|
+
/* @__PURE__ */ jsxDEV16(ScrollableLog, {
|
|
2231
2735
|
lines,
|
|
2232
2736
|
autoScroll: false
|
|
2233
2737
|
}, undefined, false, undefined, this),
|
|
2234
|
-
/* @__PURE__ */
|
|
2738
|
+
/* @__PURE__ */ jsxDEV16(Box13, {
|
|
2235
2739
|
marginTop: 1,
|
|
2236
|
-
children: /* @__PURE__ */
|
|
2740
|
+
children: /* @__PURE__ */ jsxDEV16(Text12, {
|
|
2237
2741
|
color: success ? colors.success : colors.error,
|
|
2238
2742
|
children: success ? "Done" : "Failed"
|
|
2239
2743
|
}, undefined, false, undefined, this)
|
|
2240
2744
|
}, undefined, false, undefined, this),
|
|
2241
|
-
/* @__PURE__ */
|
|
2745
|
+
/* @__PURE__ */ jsxDEV16(Text12, {
|
|
2242
2746
|
dimColor: true,
|
|
2243
2747
|
children: "Press any key to continue..."
|
|
2244
2748
|
}, undefined, false, undefined, this)
|
|
2245
2749
|
]
|
|
2246
2750
|
}, undefined, true, undefined, this);
|
|
2247
2751
|
}
|
|
2248
|
-
return /* @__PURE__ */
|
|
2752
|
+
return /* @__PURE__ */ jsxDEV16(Panel, {
|
|
2249
2753
|
title: "Package Sync",
|
|
2250
|
-
children: /* @__PURE__ */
|
|
2754
|
+
children: /* @__PURE__ */ jsxDEV16(VimSelect, {
|
|
2251
2755
|
options: [
|
|
2252
2756
|
{ label: "Sync packages", value: "sync" },
|
|
2253
2757
|
{ label: "Sync with purge", value: "sync-purge" },
|
|
@@ -2263,14 +2767,14 @@ function PackageMenu({ onBack }) {
|
|
|
2263
2767
|
}
|
|
2264
2768
|
|
|
2265
2769
|
// src/components/menus/ThemeMenu.tsx
|
|
2266
|
-
import { useState as
|
|
2267
|
-
import { Box as
|
|
2268
|
-
import { existsSync as
|
|
2269
|
-
import { join as
|
|
2770
|
+
import { useState as useState9, useEffect as useEffect5, useMemo as useMemo4 } from "react";
|
|
2771
|
+
import { Box as Box15, Text as Text14 } from "ink";
|
|
2772
|
+
import { existsSync as existsSync7, readdirSync as readdirSync5 } from "fs";
|
|
2773
|
+
import { join as join6 } from "path";
|
|
2270
2774
|
|
|
2271
2775
|
// src/components/ThemeCard.tsx
|
|
2272
|
-
import { Box as
|
|
2273
|
-
import { jsxDEV as
|
|
2776
|
+
import { Box as Box14, Text as Text13 } from "ink";
|
|
2777
|
+
import { jsxDEV as jsxDEV17 } from "react/jsx-dev-runtime";
|
|
2274
2778
|
function ThemeCard({ theme, isSelected, width }) {
|
|
2275
2779
|
const borderColor = isSelected ? colors.accent : colors.border;
|
|
2276
2780
|
const nameColor = isSelected ? colors.primary : colors.text;
|
|
@@ -2280,25 +2784,25 @@ function ThemeCard({ theme, isSelected, width }) {
|
|
|
2280
2784
|
if (theme.isLightMode)
|
|
2281
2785
|
indicators.push("light");
|
|
2282
2786
|
const indicatorText = indicators.length > 0 ? ` [${indicators.join(" ")}]` : "";
|
|
2283
|
-
return /* @__PURE__ */
|
|
2787
|
+
return /* @__PURE__ */ jsxDEV17(Box14, {
|
|
2284
2788
|
flexDirection: "column",
|
|
2285
2789
|
width,
|
|
2286
2790
|
borderStyle: borderStyles.panel,
|
|
2287
2791
|
borderColor,
|
|
2288
2792
|
paddingX: 1,
|
|
2289
|
-
children: /* @__PURE__ */
|
|
2793
|
+
children: /* @__PURE__ */ jsxDEV17(Box14, {
|
|
2290
2794
|
children: [
|
|
2291
|
-
/* @__PURE__ */
|
|
2795
|
+
/* @__PURE__ */ jsxDEV17(Text13, {
|
|
2292
2796
|
color: isSelected ? colors.accent : colors.primaryDim,
|
|
2293
2797
|
children: isSelected ? "● " : " "
|
|
2294
2798
|
}, undefined, false, undefined, this),
|
|
2295
|
-
/* @__PURE__ */
|
|
2799
|
+
/* @__PURE__ */ jsxDEV17(Text13, {
|
|
2296
2800
|
color: nameColor,
|
|
2297
2801
|
bold: true,
|
|
2298
2802
|
wrap: "truncate",
|
|
2299
2803
|
children: theme.name
|
|
2300
2804
|
}, undefined, false, undefined, this),
|
|
2301
|
-
/* @__PURE__ */
|
|
2805
|
+
/* @__PURE__ */ jsxDEV17(Text13, {
|
|
2302
2806
|
color: colors.primaryDim,
|
|
2303
2807
|
children: indicatorText
|
|
2304
2808
|
}, undefined, false, undefined, this)
|
|
@@ -2308,8 +2812,8 @@ function ThemeCard({ theme, isSelected, width }) {
|
|
|
2308
2812
|
}
|
|
2309
2813
|
|
|
2310
2814
|
// src/hooks/useThemeGrid.ts
|
|
2311
|
-
import { useState as
|
|
2312
|
-
import { useInput as
|
|
2815
|
+
import { useState as useState8, useEffect as useEffect4 } from "react";
|
|
2816
|
+
import { useInput as useInput9 } from "ink";
|
|
2313
2817
|
function useThemeGrid({
|
|
2314
2818
|
itemCount,
|
|
2315
2819
|
cardHeight = 3,
|
|
@@ -2320,8 +2824,8 @@ function useThemeGrid({
|
|
|
2320
2824
|
enabled = true
|
|
2321
2825
|
}) {
|
|
2322
2826
|
const { columns, rows } = useTerminalSize();
|
|
2323
|
-
const [selectedIndex, setSelectedIndex] =
|
|
2324
|
-
const [scrollOffset, setScrollOffset] =
|
|
2827
|
+
const [selectedIndex, setSelectedIndex] = useState8(0);
|
|
2828
|
+
const [scrollOffset, setScrollOffset] = useState8(0);
|
|
2325
2829
|
const availableWidth = columns - 6;
|
|
2326
2830
|
const cardsPerRow = Math.max(1, Math.floor(availableWidth / minCardWidth));
|
|
2327
2831
|
const cardWidth = Math.floor(availableWidth / cardsPerRow);
|
|
@@ -2336,7 +2840,7 @@ function useThemeGrid({
|
|
|
2336
2840
|
setScrollOffset(selectedRow - visibleRows + 1);
|
|
2337
2841
|
}
|
|
2338
2842
|
}, [selectedRow, scrollOffset, visibleRows]);
|
|
2339
|
-
|
|
2843
|
+
useInput9((input, key) => {
|
|
2340
2844
|
if (!enabled)
|
|
2341
2845
|
return;
|
|
2342
2846
|
if (key.escape && onBack) {
|
|
@@ -2387,8 +2891,8 @@ function useThemeGrid({
|
|
|
2387
2891
|
}
|
|
2388
2892
|
|
|
2389
2893
|
// src/lib/theme-parser.ts
|
|
2390
|
-
import { existsSync as
|
|
2391
|
-
import { join as
|
|
2894
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3 } from "fs";
|
|
2895
|
+
import { join as join4 } from "path";
|
|
2392
2896
|
function parseYaml(content) {
|
|
2393
2897
|
const result = {};
|
|
2394
2898
|
const lines = content.split(`
|
|
@@ -2419,8 +2923,8 @@ function parseYaml(content) {
|
|
|
2419
2923
|
return result;
|
|
2420
2924
|
}
|
|
2421
2925
|
async function parseThemeMetadata(themePath) {
|
|
2422
|
-
const yamlPath =
|
|
2423
|
-
if (!
|
|
2926
|
+
const yamlPath = join4(themePath, "theme.yaml");
|
|
2927
|
+
if (!existsSync5(yamlPath)) {
|
|
2424
2928
|
return;
|
|
2425
2929
|
}
|
|
2426
2930
|
try {
|
|
@@ -2442,7 +2946,7 @@ function parseThemeFiles(themePath) {
|
|
|
2442
2946
|
const entries = readdirSync3(themePath, { withFileTypes: true });
|
|
2443
2947
|
return entries.filter((e) => e.isFile() && !e.name.startsWith(".") && e.name !== "theme.yaml" && e.name !== "light.mode").map((e) => ({
|
|
2444
2948
|
name: e.name,
|
|
2445
|
-
path:
|
|
2949
|
+
path: join4(themePath, e.name),
|
|
2446
2950
|
application: e.name.replace(/\.(conf|theme|lua|toml|css|json|ini)$/, "")
|
|
2447
2951
|
}));
|
|
2448
2952
|
}
|
|
@@ -2454,16 +2958,16 @@ async function parseTheme(themePath, themeName) {
|
|
|
2454
2958
|
path: themePath,
|
|
2455
2959
|
files,
|
|
2456
2960
|
metadata,
|
|
2457
|
-
hasBackgrounds:
|
|
2458
|
-
hasPreview:
|
|
2459
|
-
isLightMode:
|
|
2961
|
+
hasBackgrounds: existsSync5(join4(themePath, "backgrounds")),
|
|
2962
|
+
hasPreview: existsSync5(join4(themePath, "preview.png")),
|
|
2963
|
+
isLightMode: existsSync5(join4(themePath, "light.mode"))
|
|
2460
2964
|
};
|
|
2461
2965
|
}
|
|
2462
2966
|
|
|
2463
2967
|
// src/cli/set-theme.ts
|
|
2464
2968
|
import { parseArgs as parseArgs4 } from "util";
|
|
2465
|
-
import { readdirSync as readdirSync4, existsSync as
|
|
2466
|
-
import { join as
|
|
2969
|
+
import { readdirSync as readdirSync4, existsSync as existsSync6, rmSync, symlinkSync, unlinkSync } from "fs";
|
|
2970
|
+
import { join as join5 } from "path";
|
|
2467
2971
|
var colors5 = {
|
|
2468
2972
|
red: "\x1B[0;31m",
|
|
2469
2973
|
green: "\x1B[0;32m",
|
|
@@ -2475,14 +2979,14 @@ var colors5 = {
|
|
|
2475
2979
|
};
|
|
2476
2980
|
async function listThemes() {
|
|
2477
2981
|
await ensureConfigDir();
|
|
2478
|
-
if (!
|
|
2982
|
+
if (!existsSync6(THEMES_DIR)) {
|
|
2479
2983
|
return [];
|
|
2480
2984
|
}
|
|
2481
2985
|
const entries = readdirSync4(THEMES_DIR, { withFileTypes: true });
|
|
2482
2986
|
const themes = [];
|
|
2483
2987
|
for (const entry of entries) {
|
|
2484
2988
|
if (entry.isDirectory()) {
|
|
2485
|
-
const themePath =
|
|
2989
|
+
const themePath = join5(THEMES_DIR, entry.name);
|
|
2486
2990
|
const theme = await parseTheme(themePath, entry.name);
|
|
2487
2991
|
themes.push(theme);
|
|
2488
2992
|
}
|
|
@@ -2490,10 +2994,10 @@ async function listThemes() {
|
|
|
2490
2994
|
return themes;
|
|
2491
2995
|
}
|
|
2492
2996
|
function clearDirectory(dir) {
|
|
2493
|
-
if (
|
|
2997
|
+
if (existsSync6(dir)) {
|
|
2494
2998
|
const entries = readdirSync4(dir, { withFileTypes: true });
|
|
2495
2999
|
for (const entry of entries) {
|
|
2496
|
-
const fullPath =
|
|
3000
|
+
const fullPath = join5(dir, entry.name);
|
|
2497
3001
|
if (entry.isSymbolicLink() || entry.isFile()) {
|
|
2498
3002
|
unlinkSync(fullPath);
|
|
2499
3003
|
} else if (entry.isDirectory()) {
|
|
@@ -2503,33 +3007,33 @@ function clearDirectory(dir) {
|
|
|
2503
3007
|
}
|
|
2504
3008
|
}
|
|
2505
3009
|
function createSymlink(source, target) {
|
|
2506
|
-
if (
|
|
3010
|
+
if (existsSync6(target)) {
|
|
2507
3011
|
unlinkSync(target);
|
|
2508
3012
|
}
|
|
2509
3013
|
symlinkSync(source, target);
|
|
2510
3014
|
}
|
|
2511
3015
|
async function applyTheme(themeName) {
|
|
2512
|
-
const themeDir =
|
|
2513
|
-
if (!
|
|
3016
|
+
const themeDir = join5(THEMES_DIR, themeName);
|
|
3017
|
+
if (!existsSync6(themeDir)) {
|
|
2514
3018
|
return { output: `Theme '${themeName}' not found`, success: false };
|
|
2515
3019
|
}
|
|
2516
3020
|
await ensureConfigDir();
|
|
2517
3021
|
await ensureDir2(THEME_TARGET_DIR);
|
|
2518
3022
|
const theme = await parseTheme(themeDir, themeName);
|
|
2519
3023
|
clearDirectory(THEME_TARGET_DIR);
|
|
2520
|
-
if (
|
|
3024
|
+
if (existsSync6(BACKGROUNDS_TARGET_DIR)) {
|
|
2521
3025
|
rmSync(BACKGROUNDS_TARGET_DIR, { recursive: true, force: true });
|
|
2522
3026
|
}
|
|
2523
3027
|
const entries = readdirSync4(themeDir, { withFileTypes: true });
|
|
2524
3028
|
for (const entry of entries) {
|
|
2525
|
-
const source =
|
|
3029
|
+
const source = join5(themeDir, entry.name);
|
|
2526
3030
|
if (entry.isFile() && entry.name !== "theme.yaml" && entry.name !== "light.mode") {
|
|
2527
|
-
const target =
|
|
3031
|
+
const target = join5(THEME_TARGET_DIR, entry.name);
|
|
2528
3032
|
createSymlink(source, target);
|
|
2529
3033
|
}
|
|
2530
3034
|
}
|
|
2531
3035
|
if (theme.hasBackgrounds) {
|
|
2532
|
-
const backgroundsSource =
|
|
3036
|
+
const backgroundsSource = join5(themeDir, "backgrounds");
|
|
2533
3037
|
createSymlink(backgroundsSource, BACKGROUNDS_TARGET_DIR);
|
|
2534
3038
|
}
|
|
2535
3039
|
let output = `Theme '${theme.name}' applied successfully`;
|
|
@@ -2548,8 +3052,8 @@ Note: This is a light mode theme`;
|
|
|
2548
3052
|
return { output, success: true };
|
|
2549
3053
|
}
|
|
2550
3054
|
async function showThemeInfo(themeName) {
|
|
2551
|
-
const themeDir =
|
|
2552
|
-
if (!
|
|
3055
|
+
const themeDir = join5(THEMES_DIR, themeName);
|
|
3056
|
+
if (!existsSync6(themeDir)) {
|
|
2553
3057
|
console.error(`${colors5.red}Error: Theme '${themeName}' not found${colors5.reset}`);
|
|
2554
3058
|
process.exit(1);
|
|
2555
3059
|
}
|
|
@@ -2631,10 +3135,10 @@ if (isMainModule4) {
|
|
|
2631
3135
|
}
|
|
2632
3136
|
|
|
2633
3137
|
// src/components/menus/ThemeMenu.tsx
|
|
2634
|
-
import { jsxDEV as
|
|
3138
|
+
import { jsxDEV as jsxDEV18 } from "react/jsx-dev-runtime";
|
|
2635
3139
|
function ThemeMenu({ onBack }) {
|
|
2636
|
-
const [themes, setThemes] =
|
|
2637
|
-
const [loading, setLoading] =
|
|
3140
|
+
const [themes, setThemes] = useState9([]);
|
|
3141
|
+
const [loading, setLoading] = useState9(true);
|
|
2638
3142
|
const { state, output, success, isRunning, isResult, execute, reset } = useMenuAction();
|
|
2639
3143
|
const grid = useThemeGrid({
|
|
2640
3144
|
itemCount: themes.length,
|
|
@@ -2644,7 +3148,7 @@ function ThemeMenu({ onBack }) {
|
|
|
2644
3148
|
});
|
|
2645
3149
|
useEffect5(() => {
|
|
2646
3150
|
async function loadThemes() {
|
|
2647
|
-
if (!
|
|
3151
|
+
if (!existsSync7(THEMES_DIR)) {
|
|
2648
3152
|
setThemes([]);
|
|
2649
3153
|
setLoading(false);
|
|
2650
3154
|
return;
|
|
@@ -2653,7 +3157,7 @@ function ThemeMenu({ onBack }) {
|
|
|
2653
3157
|
const loadedThemes = [];
|
|
2654
3158
|
for (const entry of entries) {
|
|
2655
3159
|
if (entry.isDirectory()) {
|
|
2656
|
-
const themePath =
|
|
3160
|
+
const themePath = join6(THEMES_DIR, entry.name);
|
|
2657
3161
|
const theme = await parseTheme(themePath, entry.name);
|
|
2658
3162
|
loadedThemes.push(theme);
|
|
2659
3163
|
}
|
|
@@ -2671,13 +3175,13 @@ function ThemeMenu({ onBack }) {
|
|
|
2671
3175
|
return themes.slice(grid.visibleStartIndex, grid.visibleEndIndex);
|
|
2672
3176
|
}, [themes, grid.visibleStartIndex, grid.visibleEndIndex]);
|
|
2673
3177
|
if (loading || isRunning) {
|
|
2674
|
-
return /* @__PURE__ */
|
|
3178
|
+
return /* @__PURE__ */ jsxDEV18(LoadingPanel, {
|
|
2675
3179
|
title: "Select Theme",
|
|
2676
3180
|
label: loading ? "Loading themes..." : "Applying theme..."
|
|
2677
3181
|
}, undefined, false, undefined, this);
|
|
2678
3182
|
}
|
|
2679
3183
|
if (isResult) {
|
|
2680
|
-
return /* @__PURE__ */
|
|
3184
|
+
return /* @__PURE__ */ jsxDEV18(CommandOutput, {
|
|
2681
3185
|
title: "Select Theme",
|
|
2682
3186
|
output,
|
|
2683
3187
|
success,
|
|
@@ -2685,28 +3189,28 @@ function ThemeMenu({ onBack }) {
|
|
|
2685
3189
|
}, undefined, false, undefined, this);
|
|
2686
3190
|
}
|
|
2687
3191
|
if (themes.length === 0) {
|
|
2688
|
-
return /* @__PURE__ */
|
|
3192
|
+
return /* @__PURE__ */ jsxDEV18(Panel, {
|
|
2689
3193
|
title: "Select Theme",
|
|
2690
3194
|
children: [
|
|
2691
|
-
/* @__PURE__ */
|
|
3195
|
+
/* @__PURE__ */ jsxDEV18(Box15, {
|
|
2692
3196
|
flexDirection: "column",
|
|
2693
3197
|
children: [
|
|
2694
|
-
/* @__PURE__ */
|
|
3198
|
+
/* @__PURE__ */ jsxDEV18(Text14, {
|
|
2695
3199
|
color: colors.warning,
|
|
2696
3200
|
children: "No themes available."
|
|
2697
3201
|
}, undefined, false, undefined, this),
|
|
2698
|
-
/* @__PURE__ */
|
|
3202
|
+
/* @__PURE__ */ jsxDEV18(Text14, {
|
|
2699
3203
|
children: "This system is compatible with omarchy themes."
|
|
2700
3204
|
}, undefined, false, undefined, this),
|
|
2701
|
-
/* @__PURE__ */
|
|
3205
|
+
/* @__PURE__ */ jsxDEV18(Text14, {
|
|
2702
3206
|
dimColor: true,
|
|
2703
3207
|
children: "Add themes to ~/.config/formalconf/themes/"
|
|
2704
3208
|
}, undefined, false, undefined, this)
|
|
2705
3209
|
]
|
|
2706
3210
|
}, undefined, true, undefined, this),
|
|
2707
|
-
/* @__PURE__ */
|
|
3211
|
+
/* @__PURE__ */ jsxDEV18(Box15, {
|
|
2708
3212
|
marginTop: 1,
|
|
2709
|
-
children: /* @__PURE__ */
|
|
3213
|
+
children: /* @__PURE__ */ jsxDEV18(VimSelect, {
|
|
2710
3214
|
options: [{ label: "Back", value: "back" }],
|
|
2711
3215
|
onChange: () => onBack()
|
|
2712
3216
|
}, undefined, false, undefined, this)
|
|
@@ -2714,10 +3218,10 @@ function ThemeMenu({ onBack }) {
|
|
|
2714
3218
|
]
|
|
2715
3219
|
}, undefined, true, undefined, this);
|
|
2716
3220
|
}
|
|
2717
|
-
return /* @__PURE__ */
|
|
3221
|
+
return /* @__PURE__ */ jsxDEV18(Panel, {
|
|
2718
3222
|
title: "Select Theme",
|
|
2719
3223
|
children: [
|
|
2720
|
-
grid.showScrollUp && /* @__PURE__ */
|
|
3224
|
+
grid.showScrollUp && /* @__PURE__ */ jsxDEV18(Text14, {
|
|
2721
3225
|
dimColor: true,
|
|
2722
3226
|
children: [
|
|
2723
3227
|
" ",
|
|
@@ -2727,18 +3231,18 @@ function ThemeMenu({ onBack }) {
|
|
|
2727
3231
|
grid.scrollOffset > 1 ? "s" : ""
|
|
2728
3232
|
]
|
|
2729
3233
|
}, undefined, true, undefined, this),
|
|
2730
|
-
/* @__PURE__ */
|
|
3234
|
+
/* @__PURE__ */ jsxDEV18(Box15, {
|
|
2731
3235
|
flexDirection: "row",
|
|
2732
3236
|
flexWrap: "wrap",
|
|
2733
3237
|
height: grid.gridHeight,
|
|
2734
3238
|
overflow: "hidden",
|
|
2735
|
-
children: visibleThemes.map((theme, index) => /* @__PURE__ */
|
|
3239
|
+
children: visibleThemes.map((theme, index) => /* @__PURE__ */ jsxDEV18(ThemeCard, {
|
|
2736
3240
|
theme,
|
|
2737
3241
|
isSelected: grid.visibleStartIndex + index === grid.selectedIndex,
|
|
2738
3242
|
width: grid.cardWidth
|
|
2739
3243
|
}, theme.path, false, undefined, this))
|
|
2740
3244
|
}, undefined, false, undefined, this),
|
|
2741
|
-
grid.showScrollDown && /* @__PURE__ */
|
|
3245
|
+
grid.showScrollDown && /* @__PURE__ */ jsxDEV18(Text14, {
|
|
2742
3246
|
dimColor: true,
|
|
2743
3247
|
children: [
|
|
2744
3248
|
" ",
|
|
@@ -2748,9 +3252,9 @@ function ThemeMenu({ onBack }) {
|
|
|
2748
3252
|
grid.totalRows - grid.scrollOffset - grid.visibleRows > 1 ? "s" : ""
|
|
2749
3253
|
]
|
|
2750
3254
|
}, undefined, true, undefined, this),
|
|
2751
|
-
/* @__PURE__ */
|
|
3255
|
+
/* @__PURE__ */ jsxDEV18(Box15, {
|
|
2752
3256
|
marginTop: 1,
|
|
2753
|
-
children: /* @__PURE__ */
|
|
3257
|
+
children: /* @__PURE__ */ jsxDEV18(Text14, {
|
|
2754
3258
|
dimColor: true,
|
|
2755
3259
|
children: "←→↑↓/hjkl navigate • Enter select • Esc back"
|
|
2756
3260
|
}, undefined, false, undefined, this)
|
|
@@ -2760,7 +3264,7 @@ function ThemeMenu({ onBack }) {
|
|
|
2760
3264
|
}
|
|
2761
3265
|
|
|
2762
3266
|
// src/cli/formalconf.tsx
|
|
2763
|
-
import { jsxDEV as
|
|
3267
|
+
import { jsxDEV as jsxDEV19 } from "react/jsx-dev-runtime";
|
|
2764
3268
|
var BREADCRUMBS = {
|
|
2765
3269
|
main: ["Main"],
|
|
2766
3270
|
config: ["Main", "Config Manager"],
|
|
@@ -2768,61 +3272,71 @@ var BREADCRUMBS = {
|
|
|
2768
3272
|
themes: ["Main", "Themes"]
|
|
2769
3273
|
};
|
|
2770
3274
|
function App() {
|
|
2771
|
-
const [appState, setAppState] =
|
|
2772
|
-
const [missingDeps, setMissingDeps] =
|
|
2773
|
-
const [screen, setScreen] =
|
|
3275
|
+
const [appState, setAppState] = useState10("loading");
|
|
3276
|
+
const [missingDeps, setMissingDeps] = useState10([]);
|
|
3277
|
+
const [screen, setScreen] = useState10("main");
|
|
2774
3278
|
const { exit } = useApp2();
|
|
2775
|
-
|
|
3279
|
+
useInput10((input) => {
|
|
2776
3280
|
if (input === "q")
|
|
2777
3281
|
exit();
|
|
2778
3282
|
});
|
|
2779
3283
|
useEffect6(() => {
|
|
2780
3284
|
async function init() {
|
|
2781
|
-
ensureConfigDir();
|
|
3285
|
+
await ensureConfigDir();
|
|
2782
3286
|
const result = await checkPrerequisites();
|
|
2783
3287
|
if (!result.ok) {
|
|
2784
3288
|
setMissingDeps(result.missing);
|
|
2785
3289
|
setAppState("error");
|
|
2786
|
-
|
|
2787
|
-
setAppState("ready");
|
|
3290
|
+
return;
|
|
2788
3291
|
}
|
|
3292
|
+
const firstRun = await isFirstRun();
|
|
3293
|
+
if (firstRun) {
|
|
3294
|
+
setAppState("onboarding");
|
|
3295
|
+
return;
|
|
3296
|
+
}
|
|
3297
|
+
setAppState("ready");
|
|
2789
3298
|
}
|
|
2790
3299
|
init();
|
|
2791
3300
|
}, []);
|
|
2792
3301
|
if (appState === "loading") {
|
|
2793
|
-
return /* @__PURE__ */
|
|
3302
|
+
return /* @__PURE__ */ jsxDEV19(Layout, {
|
|
2794
3303
|
breadcrumb: ["Loading"],
|
|
2795
|
-
children: /* @__PURE__ */
|
|
3304
|
+
children: /* @__PURE__ */ jsxDEV19(Panel, {
|
|
2796
3305
|
title: "FormalConf",
|
|
2797
|
-
children: /* @__PURE__ */
|
|
3306
|
+
children: /* @__PURE__ */ jsxDEV19(Spinner2, {
|
|
2798
3307
|
label: "Checking prerequisites..."
|
|
2799
3308
|
}, undefined, false, undefined, this)
|
|
2800
3309
|
}, undefined, false, undefined, this)
|
|
2801
3310
|
}, undefined, false, undefined, this);
|
|
2802
3311
|
}
|
|
2803
3312
|
if (appState === "error") {
|
|
2804
|
-
return /* @__PURE__ */
|
|
3313
|
+
return /* @__PURE__ */ jsxDEV19(PrerequisiteError, {
|
|
2805
3314
|
missing: missingDeps,
|
|
2806
3315
|
onExit: exit
|
|
2807
3316
|
}, undefined, false, undefined, this);
|
|
2808
3317
|
}
|
|
3318
|
+
if (appState === "onboarding") {
|
|
3319
|
+
return /* @__PURE__ */ jsxDEV19(Onboarding, {
|
|
3320
|
+
onComplete: () => setAppState("ready")
|
|
3321
|
+
}, undefined, false, undefined, this);
|
|
3322
|
+
}
|
|
2809
3323
|
const goBack = () => setScreen("main");
|
|
2810
|
-
return /* @__PURE__ */
|
|
3324
|
+
return /* @__PURE__ */ jsxDEV19(Layout, {
|
|
2811
3325
|
breadcrumb: BREADCRUMBS[screen],
|
|
2812
3326
|
children: [
|
|
2813
|
-
screen === "main" && /* @__PURE__ */
|
|
3327
|
+
screen === "main" && /* @__PURE__ */ jsxDEV19(MainMenu, {
|
|
2814
3328
|
onSelect: setScreen
|
|
2815
3329
|
}, undefined, false, undefined, this),
|
|
2816
|
-
screen === "config" && /* @__PURE__ */
|
|
3330
|
+
screen === "config" && /* @__PURE__ */ jsxDEV19(ConfigMenu, {
|
|
2817
3331
|
onBack: goBack
|
|
2818
3332
|
}, undefined, false, undefined, this),
|
|
2819
|
-
screen === "packages" && /* @__PURE__ */
|
|
3333
|
+
screen === "packages" && /* @__PURE__ */ jsxDEV19(PackageMenu, {
|
|
2820
3334
|
onBack: goBack
|
|
2821
3335
|
}, undefined, false, undefined, this),
|
|
2822
|
-
screen === "themes" && /* @__PURE__ */
|
|
3336
|
+
screen === "themes" && /* @__PURE__ */ jsxDEV19(ThemeMenu, {
|
|
2823
3337
|
onBack: goBack
|
|
2824
3338
|
}, undefined, false, undefined, this)
|
|
2825
3339
|
]
|
|
2826
3340
|
}, undefined, true, undefined, this);
|
|
2827
3341
|
}
|
|
2828
|
-
render(/* @__PURE__ */
|
|
3342
|
+
render(/* @__PURE__ */ jsxDEV19(App, {}, undefined, false, undefined, this));
|