github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/pkg/helper/list.go (about) 1 package helper 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "regexp" 8 "sort" 9 "strings" 10 11 "github.com/360EntSecGroup-Skylar/excelize/v2" 12 consts "github.com/easysoft/zendata/internal/pkg/const" 13 "github.com/easysoft/zendata/internal/pkg/domain" 14 "github.com/easysoft/zendata/internal/pkg/model" 15 fileUtils "github.com/easysoft/zendata/pkg/utils/file" 16 i118Utils "github.com/easysoft/zendata/pkg/utils/i118" 17 logUtils "github.com/easysoft/zendata/pkg/utils/log" 18 "github.com/easysoft/zendata/pkg/utils/vari" 19 "github.com/mattn/go-runewidth" 20 "gopkg.in/yaml.v3" 21 ) 22 23 func ListData() { 24 res := map[string][]domain.ResFile{} 25 GetFilesAndDirs(consts.ResDirUsers, consts.ResDirUsers, &res) 26 27 res, nameWidth, titleWidth := LoadRes(res) 28 PrintRes(res, nameWidth, titleWidth) 29 } 30 31 func ListRes() (ret map[string][]domain.ResFile) { 32 res, nameWidth, titleWidth := GetRes() 33 PrintRes(res, nameWidth, titleWidth) 34 35 return 36 } 37 38 func GetRes() (ret map[string][]domain.ResFile, nameWidth, titleWidth int) { 39 ret = map[string][]domain.ResFile{} 40 41 for _, key := range consts.ResKeys { 42 GetFilesAndDirs(key, key, &ret) 43 } 44 45 ret, nameWidth, titleWidth = LoadRes(ret) 46 47 return 48 } 49 50 func LoadRes(res map[string][]domain.ResFile) (ret map[string][]domain.ResFile, nameWidth, titleWidth int) { 51 ret = map[string][]domain.ResFile{} 52 53 for _, key := range consts.ResKeys { 54 arr := make([]domain.ResFile, 0) 55 56 for _, item := range res[key] { 57 pth := item.Path 58 59 fileExt := filepath.Ext(pth) 60 isArticleFiles := false 61 var title, desc, tp string 62 63 if key == consts.ResDirData { // data dir contains excel 64 title, desc, tp = ReadExcelInfo(pth) 65 } else if key == consts.ResDirYaml || key == consts.ResDirUsers { 66 isArticleFiles, _ = regexp.MatchString("yaml.article", pth) 67 68 if fileExt == ".txt" { // ignore packaged article text file 69 title, desc, tp = ReadTextInfo(pth, key) 70 } else { 71 title, desc, tp = ReadYamlInfo(pth) 72 } 73 } 74 75 item.ReferName = PathToName(pth, key, tp) 76 item.Title = title 77 item.Desc = desc 78 item.ResType = tp 79 80 lent := runewidth.StringWidth(item.ReferName) 81 if lent > nameWidth { 82 nameWidth = lent 83 } 84 85 if key == consts.ResDirData { 86 sheets := strings.Split(title, "|") 87 for _, sheet := range sheets { 88 lent2 := runewidth.StringWidth(sheet) 89 if lent2 > titleWidth { 90 titleWidth = lent2 91 } 92 } 93 } else { 94 lent2 := runewidth.StringWidth(title) 95 if lent2 > titleWidth { 96 titleWidth = lent2 97 } 98 } 99 100 if !isArticleFiles { 101 arr = append(arr, item) 102 } 103 } 104 105 ret[key] = SortByName(arr) 106 } 107 108 return 109 } 110 111 func PrintRes(res map[string][]domain.ResFile, nameWidth, titleWidth int) { 112 dataMsg := "" 113 yamlMsg := "" 114 usersMsg := "" 115 idx := 0 116 117 for _, key := range consts.ResKeys { 118 arr := res[key] 119 120 for _, item := range arr { 121 name := item.ReferName 122 desc := item.Desc 123 title := item.Title 124 titles := strings.Split(title, "|") 125 126 idx2 := 0 127 for _, title := range titles { 128 if idx2 > 0 { 129 name = "" 130 } 131 name = name + strings.Repeat(" ", nameWidth-runewidth.StringWidth(name)) 132 133 title = title + strings.Repeat(" ", titleWidth-runewidth.StringWidth(title)) 134 msg := fmt.Sprintf("%s %s %s\n", name, title, desc) 135 136 if key == consts.ResDirData { 137 dataMsg = dataMsg + msg 138 } else if key == consts.ResDirYaml { 139 yamlMsg = yamlMsg + msg 140 } else if key == consts.ResDirUsers { 141 usersMsg = usersMsg + msg 142 } 143 144 idx2++ 145 } 146 147 idx++ 148 } 149 } 150 151 if dataMsg != "" { 152 logUtils.PrintTo(strings.TrimSpace(dataMsg) + "\n") 153 } 154 if yamlMsg != "" { 155 logUtils.PrintTo(strings.TrimSpace(yamlMsg) + "\n") 156 } 157 if usersMsg != "" { 158 logUtils.PrintTo(strings.TrimSpace(usersMsg)) 159 } 160 } 161 162 func GetFilesAndDirs(pth, typ string, res *map[string][]domain.ResFile) { 163 if !fileUtils.IsAbsPath(pth) { 164 pth = vari.WorkDir + pth 165 } 166 167 dir, err := os.ReadDir(pth) 168 if err != nil { 169 return 170 } 171 172 for _, fi := range dir { 173 if fi.IsDir() { 174 GetFilesAndDirs(filepath.Join(pth, fi.Name()), typ, res) 175 } else { 176 name := fi.Name() 177 fileExt := filepath.Ext(name) 178 if fileExt != ".yaml" && fileExt != ".xlsx" && fileExt != ".txt" { 179 continue 180 } 181 182 info, _ := fi.Info() 183 file := domain.ResFile{Path: filepath.Join(pth, name), UpdatedAt: info.ModTime()} 184 (*res)[typ] = append((*res)[typ], file) 185 } 186 } 187 } 188 189 func ReadYamlInfo(path string) (title, desc, resType string) { 190 info := domain.DefInfo{} 191 192 if strings.Index(path, "apache") > -1 { 193 logUtils.PrintTo("") 194 } 195 196 yamlContent, err := os.ReadFile(path) 197 if err != nil { 198 logUtils.PrintTo(i118Utils.I118Prt.Sprintf("fail_to_read_file", path)) 199 return 200 } 201 err = yaml.Unmarshal(yamlContent, &info) 202 if err != nil { 203 logUtils.PrintTo(i118Utils.I118Prt.Sprintf("fail_to_parse_file", path)) 204 return 205 } 206 207 title = info.Title 208 desc = info.Desc 209 resType = GetYamlResType(info) 210 return 211 } 212 213 func ReadExcelInfo(path string) (title, desc, resType string) { 214 excel, err := excelize.OpenFile(path) 215 if err != nil { 216 logUtils.PrintTo(i118Utils.I118Prt.Sprintf("fail_to_read_file", path)) 217 return 218 } 219 220 for index, sheet := range excel.GetSheetList() { 221 if index > 0 { 222 title = title + "|" 223 } 224 title = title + sheet 225 } 226 227 desc = i118Utils.I118Prt.Sprintf("excel_data") 228 resType = consts.ResTypeExcel 229 return 230 } 231 232 func ReadTextInfo(path, key string) (title, desc, resType string) { 233 title = PathToName(path, key, consts.ResTypeText) 234 desc = i118Utils.I118Prt.Sprintf("text_data") 235 resType = consts.ResTypeText 236 return 237 } 238 239 func PathToName(path, key, tp string) string { 240 isWorkData := strings.Index(path, vari.WorkDir) > -1 241 if isWorkData { // user data in workdir 242 path = strings.Replace(path, vari.WorkDir, "", 1) 243 } 244 245 nameSep := consts.PthSep 246 if tp != consts.ResTypeText && tp != consts.ResTypeYaml && tp != consts.ResTypeConfig { 247 nameSep = "." 248 path = strings.ReplaceAll(path, consts.PthSep, nameSep) 249 path = path[strings.Index(path, nameSep)+len(nameSep):] 250 } 251 if isWorkData { 252 return path 253 } 254 255 sep := nameSep + key + nameSep 256 name := path[strings.Index(path, sep)+len(sep):] 257 if key == consts.ResDirData { // remove .xlsx postfix for excel data 258 name = name[:strings.LastIndex(name, nameSep)] 259 } 260 261 return name 262 } 263 func removeDirPrefix(name, seq string) (ret string) { 264 265 return 266 } 267 268 func SortByName(arr []domain.ResFile) []domain.ResFile { 269 sort.Slice(arr, func(i, j int) bool { 270 flag := false 271 if arr[i].ReferName > (arr[j].ReferName) { 272 flag = true 273 } 274 return flag 275 }) 276 return arr 277 } 278 279 func GetYamlResType(def domain.DefInfo) string { 280 if def.Ranges != nil { 281 return consts.ResTypeRanges 282 } else if def.Instances != nil { 283 return consts.ResTypeInstances 284 } else if def.Fields != nil { 285 return consts.ResTypeYaml 286 } else { 287 return consts.ResTypeConfig 288 } 289 290 return "" 291 } 292 293 func GetDefFromYamlFile(path string) (po *model.ZdDef, content string, err error) { 294 po = &model.ZdDef{} 295 contentByte, _ := os.ReadFile(path) 296 content = string(contentByte) 297 298 yamlContent := ReplaceSpecialChars(contentByte) 299 err = yaml.Unmarshal(yamlContent, po) 300 301 return 302 } 303 304 func GetDefFromYamlString(content string) (po *model.ZdDef, err error) { 305 po = &model.ZdDef{} 306 yamlContent := ReplaceSpecialChars([]byte(content)) 307 err = yaml.Unmarshal(yamlContent, po) 308 309 return 310 }