11package env
22
33import (
4+ "cmp"
45 "fmt"
56 "os"
6-
7- "github.com/insei/tinyconf"
7+ "reflect"
8+ "slices"
9+ "strings"
810
911 "github.com/insei/cast"
10- "github.com/insei/fmap/v2"
12+ "github.com/insei/fmap/v3"
13+ "github.com/insei/tinyconf"
1114)
1215
1316type envDriver struct {
@@ -34,6 +37,84 @@ func (d envDriver) GetName() string {
3437 return d .name
3538}
3639
40+ type field struct {
41+ path string
42+ value any
43+ depth int
44+ tag reflect.StructTag
45+ }
46+
47+ func (f field ) genDoc (driver string ) string {
48+ if tagDriver , ok := f .tag .Lookup (driver ); ok {
49+ tagDoc := f .tag .Get ("doc" )
50+ return fmt .Sprintf ("#%s\n #%s=%v\n " , tagDoc , tagDriver , f .value )
51+ }
52+ return ""
53+ }
54+
55+ func (d envDriver ) getUniqueFields (registers []tinyconf.Registered ) []field {
56+ var fields []field
57+ for _ , register := range registers {
58+ for _ , path := range register .Storage .GetAllPaths () {
59+ fld := register .Storage .MustFind (path )
60+
61+ tag := fld .GetTag ()
62+ tagDriver , ok := tag .Lookup (d .name )
63+ if ! ok {
64+ continue
65+ }
66+
67+ member := field {
68+ path : strings .Split (tagDriver , "_" )[0 ],
69+ value : fld .Get (register .Config ),
70+ depth : strings .Count (tagDriver , "_" ),
71+ tag : tag ,
72+ }
73+
74+ if slices .ContainsFunc (fields , func (item field ) bool {
75+ return item .tag .Get (d .name ) == member .tag .Get (d .name )
76+ }) {
77+ continue
78+ }
79+ fields = append (fields , member )
80+ }
81+ }
82+ return fields
83+ }
84+
85+ func (d envDriver ) getRootMap (fields []field ) map [int ]map [string ]string {
86+ roots := make (map [int ]map [string ]string )
87+ root := make (map [string ]string )
88+
89+ for _ , field := range fields {
90+ root [field .path ] += field .genDoc (d .name )
91+ roots [field .depth ] = root
92+ }
93+ return roots
94+ }
95+
96+ func (d envDriver ) GenDoc (registers ... tinyconf.Registered ) string {
97+ uniqueFields := d .getUniqueFields (registers )
98+
99+ sortedFields := slices .Clone (uniqueFields )
100+ slices .SortStableFunc (sortedFields , func (i , j field ) int {
101+ return cmp .Compare (j .depth , i .depth )
102+ })
103+
104+ roots := d .getRootMap (sortedFields )
105+ marks := make ([]string , 0 )
106+
107+ var doc string
108+ for _ , field := range uniqueFields {
109+ if slices .Contains (marks , field .path ) {
110+ continue
111+ }
112+ marks = append (marks , field .path )
113+ doc += roots [field.depth ][field.path ] + "\n "
114+ }
115+ return doc
116+ }
117+
37118func New () (tinyconf.Driver , error ) {
38119 return envDriver {
39120 name : "env" ,
0 commit comments