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  }