fix: support Home Manager declarations format in parser
The options.json parser expected declarations as []string (NixOS format),
but Home Manager uses [{name, url}] objects. This caused most HM options
to be silently skipped during parsing (27 vs 4880 options).
Changes:
- Parse declarations as json.RawMessage and try both formats
- Handle HM path format <home-manager/modules/...> in normalizeDeclarationPath
- Add /modules/ marker for HM store paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ type ParsedOption struct {
|
||||
|
||||
// optionJSON is the internal structure for parsing options.json entries.
|
||||
type optionJSON struct {
|
||||
Declarations []string `json:"declarations"`
|
||||
Declarations json.RawMessage `json:"declarations"` // Can be []string or []{name, url}
|
||||
Default json.RawMessage `json:"default,omitempty"`
|
||||
Description interface{} `json:"description"` // Can be string or object
|
||||
Example json.RawMessage `json:"example,omitempty"`
|
||||
@@ -58,11 +58,8 @@ func parseOption(name string, data json.RawMessage) (*ParsedOption, error) {
|
||||
// Handle description which can be a string or an object with _type: "mdDoc"
|
||||
description := extractDescription(opt.Description)
|
||||
|
||||
// Convert declarations to relative paths
|
||||
declarations := make([]string, 0, len(opt.Declarations))
|
||||
for _, d := range opt.Declarations {
|
||||
declarations = append(declarations, normalizeDeclarationPath(d))
|
||||
}
|
||||
// Parse declarations - can be []string (NixOS) or []{name, url} (Home Manager)
|
||||
declarations := parseDeclarations(opt.Declarations)
|
||||
|
||||
return &ParsedOption{
|
||||
Name: name,
|
||||
@@ -75,6 +72,39 @@ func parseOption(name string, data json.RawMessage) (*ParsedOption, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// parseDeclarations handles both NixOS format ([]string) and Home Manager format ([]{name, url}).
|
||||
func parseDeclarations(raw json.RawMessage) []string {
|
||||
if len(raw) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Try []string first (NixOS format)
|
||||
var stringDecls []string
|
||||
if err := json.Unmarshal(raw, &stringDecls); err == nil {
|
||||
result := make([]string, 0, len(stringDecls))
|
||||
for _, d := range stringDecls {
|
||||
result = append(result, normalizeDeclarationPath(d))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Try []{name, url} format (Home Manager format)
|
||||
var objectDecls []struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &objectDecls); err == nil {
|
||||
result := make([]string, 0, len(objectDecls))
|
||||
for _, d := range objectDecls {
|
||||
// Use name field, normalize the path
|
||||
result = append(result, normalizeDeclarationPath(d.Name))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractDescription extracts the description string from various formats.
|
||||
func extractDescription(desc interface{}) string {
|
||||
switch v := desc.(type) {
|
||||
@@ -93,16 +123,29 @@ func extractDescription(desc interface{}) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// normalizeDeclarationPath converts a full store path to a relative nixpkgs path.
|
||||
// Input: "/nix/store/xxx-source/nixos/modules/services/web-servers/nginx/default.nix"
|
||||
// Output: "nixos/modules/services/web-servers/nginx/default.nix"
|
||||
// normalizeDeclarationPath converts a full store path to a relative path.
|
||||
// NixOS input: "/nix/store/xxx-source/nixos/modules/services/web-servers/nginx/default.nix"
|
||||
// NixOS output: "nixos/modules/services/web-servers/nginx/default.nix"
|
||||
// HM input: "<home-manager/modules/programs/git.nix>"
|
||||
// HM output: "modules/programs/git.nix"
|
||||
func normalizeDeclarationPath(path string) string {
|
||||
// Look for common prefixes and strip them
|
||||
// Handle Home Manager format: <home-manager/path> or <nixpkgs/path>
|
||||
if len(path) > 2 && path[0] == '<' && path[len(path)-1] == '>' {
|
||||
inner := path[1 : len(path)-1]
|
||||
// Strip the prefix (home-manager/, nixpkgs/, etc.)
|
||||
if idx := findSubstring(inner, "/"); idx >= 0 {
|
||||
return inner[idx+1:]
|
||||
}
|
||||
return inner
|
||||
}
|
||||
|
||||
// Look for common prefixes and strip them (NixOS store paths)
|
||||
markers := []string{
|
||||
"/nixos/",
|
||||
"/pkgs/",
|
||||
"/lib/",
|
||||
"/maintainers/",
|
||||
"/modules/", // For home-manager paths
|
||||
}
|
||||
|
||||
for _, marker := range markers {
|
||||
|
||||
Reference in New Issue
Block a user