From 7e7eebae540244ec4ca2b33deba0751bc8b1a440 Mon Sep 17 00:00:00 2001 From: vinson Date: Wed, 11 Nov 2020 16:32:36 +0800 Subject: [PATCH] feat(optimize): add ask step --- README.MD | 20 ++++++----- README_zh.MD | 19 +++++----- go.mod | 5 +++ main.go | 47 ++++++++++++++++-------- parsor/showdoc.go | 1 - statement/context.go | 1 - statement/request.go | 1 - utils/selection.go | 86 ++++++++++++++++++++++++++++++++++++++++++++ utils/system.go | 34 ++++++++++++++++++ utils/utils.go | 25 ++++++++++++- 10 files changed, 205 insertions(+), 34 deletions(-) create mode 100644 utils/selection.go create mode 100644 utils/system.go diff --git a/README.MD b/README.MD index ae1b764..f6d2d4a 100644 --- a/README.MD +++ b/README.MD @@ -8,14 +8,18 @@ Write matching comments at the interface layer and execute the program .js .go .java .php file is currently available for scanning. Please add other types to compile ### Script parameter description -> -type (the document type) - -url (upload the address) - -key (project api key) - -token (project api token) - -speed (number of concurrent upload requests) - -cat (base 64 encoding of fixed directory, directory using / split) - -searchPath (the directory or file in which the scan is performed) - -templatePath (template file path) + +| parameter name | use | type | +|--------|----------|----------| +|type| the document type|string +|url| upload the address|string +|key| project api key|string +|token| project api token|string +|speed| number of concurrent upload requests|int +|cat| base 64 encoding of fixed directory, directory using / split|string +|searchPath | the directory or file in which the scan is performed|string +|templatePath| template file path|string +|ask| Ask first, then execute the program|boolean ### The annotation examples ``` diff --git a/README_zh.MD b/README_zh.MD index 1433da4..eaf8fe3 100644 --- a/README_zh.MD +++ b/README_zh.MD @@ -7,14 +7,17 @@ .js .go .java .php文件目前可用于扫描,其他类型请自行添加 ### 脚本参数说明 -> -type 文档系统类型 - -url 上传地址 - -key 项目api_key - -token 项目api_token - -speed 上传请求并发速度 - -cat 前置固定目录的base64 - -searchPath 目录/文件 - -templatePath 模板文件路径 +| 参数名 | 用途 | 类型 +|--------|----------|----------| +|type| 文档系统类型|string +|url| 上传地址|string +|key| 项目api_key|string +|token| 项目api_token|string +|speed| 上传请求并发速度|int +|cat| 前置固定目录的base64|string +|searchPath | 目录/文件|string +|templatePath| 模板文件路径|string +|ask| 是否先询问再继续执行|boolean ### 注释示例 ``` diff --git a/go.mod b/go.mod index 5f7abb6..ca87819 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module annotation-parse go 1.15 + +require ( + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/nsf/termbox-go v0.0.0-20201107200903-9b52a5faed9e +) diff --git a/main.go b/main.go index 838c1ca..b0e641c 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,3 @@ -// Copyright The ef Co. ltd All rights reserved. // Created by vinson on 2020/10/30. package main @@ -37,6 +36,7 @@ var cat string var speed int var searchPath string var templatePath string +var ask bool func main() { t1 := time.Now() @@ -52,17 +52,20 @@ func main() { flag.StringVar(&searchPath, "searchPath", "./controller", "search path") flag.StringVar(&templatePath, "templatePath", "./template.txt", "customer template file path") flag.IntVar(&speed, "speed", 1, "for Concurrent requests") + flag.BoolVar(&ask, "ask", true, "Ask first, then execute the program") flag.Parse() - fmt.Println(fmt.Sprintf("#\n"+ - "# start\n"+ - "# type: %s \n"+ - "# url: %s\n"+ - "# cat: %s\n"+ - "# search_path: %s\n"+ - "# template: %s\n"+ - "# multipost: %d\n"+ - "#", - t, URL, cat, searchPath, templatePath, speed)) + var head = func() { + fmt.Println(fmt.Sprintf("#\n"+ + "# start\n"+ + "# type: %s \n"+ + "# url: %s\n"+ + "# cat: %s\n"+ + "# search_path: %s\n"+ + "# template: %s\n"+ + "# multipost: %d\n"+ + "#", + t, URL, cat, searchPath, templatePath, speed)) + } var ps *statement.Context // get context switch t { @@ -80,15 +83,28 @@ func main() { return } if ok, fileInfo := utils.IsDir(searchPath); ok { - files, err := ioutil.ReadDir(searchPath) + // read the file list of searchPath and be sort they by modify time + // wait for user select any options to continue + files, err := utils.ReadDirOrderByModify(searchPath) if nil != err { fmt.Println(err) return } - Scan(ps, &files, rq, t, &wg, searchPath) + selection := -1 + if ask { + selection = utils.Selection(&files) + } + head() + if selection == -1 { + Scan(ps, &files, rq, t, &wg, searchPath) + } else { + ParseFile(ps, &(files[selection]), rq, t, &wg, true, searchPath) + } } else { + // 单文件直接执行 ParseFile(ps, fileInfo, rq, t, &wg, false, searchPath) } + // redundant if len(*rq) > 0 { wg.Add(len(*rq)) for _, request := range *rq { @@ -130,6 +146,7 @@ func ParseFile(ctx *statement.Context, f *os.FileInfo, fs *[]*statement.Request, fp = parentPath } if !utils.IsContain(ExtSupported, path.Ext(fp)) { + fmt.Println("file type is not supported") return } content, err := utils.ReadAll(fp) @@ -170,6 +187,8 @@ func ParseFile(ctx *statement.Context, f *os.FileInfo, fs *[]*statement.Request, } }() } + } else { + fmt.Println("reg initialize Failed") } } @@ -189,7 +208,7 @@ type Content struct { Number string // number int } -// 将一条注释解析成Content +// the function can parse the annotation str to a Content obj func Parse(annotation string) (*Content, error) { // 解析@ if !strings.Contains(annotation, CiFlag) { diff --git a/parsor/showdoc.go b/parsor/showdoc.go index a144f7c..cc67f3d 100644 --- a/parsor/showdoc.go +++ b/parsor/showdoc.go @@ -1,4 +1,3 @@ -// Copyright The ef Co. ltd All rights reserved. // Created by vinson on 2020/11/4. // ShowDoc Scanner diff --git a/statement/context.go b/statement/context.go index 7c1edbf..a188a72 100644 --- a/statement/context.go +++ b/statement/context.go @@ -1,4 +1,3 @@ -// Copyright The ef Co. All rights reserved. // Created by vinson on 2020/11/4. package statement diff --git a/statement/request.go b/statement/request.go index ce356d9..ff56625 100644 --- a/statement/request.go +++ b/statement/request.go @@ -1,4 +1,3 @@ -// Copyright The ef Co. All rights reserved. // Created by vinson on 2020/11/4. package statement diff --git a/utils/selection.go b/utils/selection.go new file mode 100644 index 0000000..3591358 --- /dev/null +++ b/utils/selection.go @@ -0,0 +1,86 @@ +// Created by vinson on 2020/11/4. + +package utils + +import ( + "fmt" + term "github.com/nsf/termbox-go" + "os" + "strings" +) + +func reset() { + _ = term.Sync() +} + +// Selection the function receive an array of fileInfo +// return the array index from user selected, -1 means selected all +func Selection(files *[]os.FileInfo) int { + var isExit = false + err := term.Init() + if err != nil { + panic(err) + } + defer func() { + term.Close() + if isExit { + os.Exit(0) + } + }() + // 打印到控制到等待输入 + selectIndex := -1 +loop: + for { + switch ev := term.PollEvent(); ev.Type { + case term.EventKey: + switch ev.Key { + case term.KeyArrowUp: + reset() + selectIndex-- + case term.KeyArrowDown: + reset() + selectIndex++ + case term.KeyEnter: + reset() + break loop + case term.KeyEsc: + reset() + isExit = true + break loop + default: + reset() + fmt.Println("Invalid input") + } + case term.EventError: + panic(ev.Err) + } + switch { + case selectIndex < -1: + selectIndex = -1 + case selectIndex > len(*files)-1: + selectIndex = len(*files) - 1 + default: + CallClear() + var fsBuilder strings.Builder + fsBuilder.WriteString("\033[1;32;40mPlease select and continue or press ESC to exit\033[0m\n\n") + if selectIndex == -1 { + fsBuilder.WriteString("\033[4;33;40mAll\033[0m\n") + } else { + fsBuilder.WriteString("All\n") + } + for i, f := range *files { + if i == selectIndex { + fsBuilder.WriteString("\033[4;33;40m") + fsBuilder.WriteString(f.Name()) + fsBuilder.WriteString("\033[0m\n") + } else { + fsBuilder.WriteString(f.Name()) + fsBuilder.WriteString("\n") + } + } + fmt.Print(fsBuilder.String()) + } + } + CallClear() + return selectIndex +} diff --git a/utils/system.go b/utils/system.go new file mode 100644 index 0000000..8afa5d1 --- /dev/null +++ b/utils/system.go @@ -0,0 +1,34 @@ +// Created by vinson on 2020/11/11. + +package utils + +import ( + "os" + "os/exec" + "runtime" +) + +var clear map[string]func() + +func init() { + clear = make(map[string]func()) + clear["linux"] = func() { + cmd := exec.Command("clear") + cmd.Stdout = os.Stdout + _ = cmd.Run() + } + clear["windows"] = func() { + cmd := exec.Command("cmd", "/c", "cls") + cmd.Stdout = os.Stdout + _ = cmd.Run() + } +} + +func CallClear() { + value, ok := clear[runtime.GOOS] // runtime.GOOS -> linux, windows, darwin etc. + if ok { //if we defined a clear func for that platform: + value() //we execute it + } else { //unsupported platform + panic("Your platform is unsupported! I can't clear terminal screen :(") + } +} diff --git a/utils/utils.go b/utils/utils.go index 257c5f1..78076e8 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,4 +1,3 @@ -// Copyright The ef Co. ltd All rights reserved. // Created by vinson on 2020/11/4. package utils @@ -7,6 +6,7 @@ import ( "io/ioutil" "os" "path" + "sort" "text/template" ) @@ -51,3 +51,26 @@ func GetTemplate(path string) (*template.Template, error) { files := []string{path} return template.ParseFiles(files...) } + +func ReadDirOrderByModify(dirname string) ([]os.FileInfo, error) { + fs, err := ioutil.ReadDir(dirname) + if err != nil { + return fs, err + } + return sortByTime(fs), nil +} + +func sortByTime(pl []os.FileInfo) []os.FileInfo { + sort.Slice(pl, func(i, j int) bool { + flag := false + if pl[i].ModTime().After(pl[j].ModTime()) { + flag = true + } else if pl[i].ModTime().Equal(pl[j].ModTime()) { + if pl[i].Name() < pl[j].Name() { + flag = true + } + } + return flag + }) + return pl +}