From 1ece26354d36b4eefbfb325cd4d26cfda877ea2b Mon Sep 17 00:00:00 2001 From: Hideo Hattori Date: Wed, 19 Jul 2023 22:39:20 +0900 Subject: [PATCH] impl: sort option --- cmd/gocloc/main.go | 39 +++++++++++++++++++++++++++++++------- file.go | 38 +++++++++++++++++++++++++++++-------- language.go | 47 ++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 101 insertions(+), 23 deletions(-) diff --git a/cmd/gocloc/main.go b/cmd/gocloc/main.go index ef72d00..493607a 100644 --- a/cmd/gocloc/main.go +++ b/cmd/gocloc/main.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "regexp" - "sort" "strings" "github.com/hhatto/gocloc" @@ -43,7 +42,7 @@ var rowLen = 79 // It is necessary to use notation that follows go-flags. type CmdOptions struct { Byfile bool `long:"by-file" description:"report results for every encountered source file"` - SortTag string `long:"sort" default:"code" description:"sort based on a certain column"` + SortTag string `long:"sort" default:"code" description:"sort based on a certain column" choice:"name" choice:"files" choice:"blank" choice:"comment" choice:"code"` OutputType string `long:"output-type" default:"default" description:"output type [values: default,cloc-xml,sloccount,json]"` ExcludeExt string `long:"exclude-ext" description:"exclude file name extensions (separated commas)"` IncludeLang string `long:"include-lang" description:"include language name (separated commas)"` @@ -103,7 +102,7 @@ func (o *outputBuilder) WriteFooter() { } } -func writeResultWithByFile(outputType string, result *gocloc.Result) { +func writeResultWithByFile(opts *CmdOptions, result *gocloc.Result) { clocFiles := result.Files total := result.Total maxPathLen := result.MaxPathLength @@ -112,9 +111,18 @@ func writeResultWithByFile(outputType string, result *gocloc.Result) { for _, file := range clocFiles { sortedFiles = append(sortedFiles, *file) } - sort.Sort(sortedFiles) + switch opts.SortTag { + case "name": + sortedFiles.SortByName() + case "comment": + sortedFiles.SortByComments() + case "blank": + sortedFiles.SortByBlanks() + default: + sortedFiles.SortByCode() + } - switch outputType { + switch opts.OutputType { case OutputTypeClocXML: t := gocloc.XMLTotalFiles{ Code: total.Code, @@ -166,7 +174,7 @@ func (o *outputBuilder) WriteResult() { total := o.result.Total if o.opts.Byfile { - writeResultWithByFile(o.opts.OutputType, o.result) + writeResultWithByFile(o.opts, o.result) } else { var sortedLanguages gocloc.Languages for _, language := range clocLangs { @@ -174,7 +182,18 @@ func (o *outputBuilder) WriteResult() { sortedLanguages = append(sortedLanguages, *language) } } - sort.Sort(sortedLanguages) + switch o.opts.SortTag { + case "name": + sortedLanguages.SortByName() + case "files": + sortedLanguages.SortByFiles() + case "comment": + sortedLanguages.SortByComments() + case "blank": + sortedLanguages.SortByBlanks() + default: + sortedLanguages.SortByCode() + } switch o.opts.OutputType { case OutputTypeClocXML: @@ -231,6 +250,12 @@ func main() { return } + // check sort tag option with other options + if opts.Byfile && opts.SortTag == "files" { + fmt.Println("`--sort files` option cannot be used in conjunction with the `--by-file` option") + os.Exit(1) + } + // setup option for exclude extensions for _, ext := range strings.Split(opts.ExcludeExt, ",") { e, ok := gocloc.Exts[ext] diff --git a/file.go b/file.go index b042319..3bfebbc 100644 --- a/file.go +++ b/file.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "sort" "strings" "unicode" ) @@ -21,17 +22,38 @@ type ClocFile struct { // ClocFiles is gocloc result set. type ClocFiles []ClocFile -func (cf ClocFiles) Len() int { - return len(cf) +func (cf ClocFiles) SortByName() { + sortFunc := func(i, j int) bool { + return cf[i].Name < cf[j].Name + } + sort.Slice(cf, sortFunc) } -func (cf ClocFiles) Swap(i, j int) { - cf[i], cf[j] = cf[j], cf[i] + +func (cf ClocFiles) SortByComments() { + sortFunc := func(i, j int) bool { + if cf[i].Comments == cf[j].Comments { + return cf[i].Code > cf[j].Code + } + return cf[i].Comments > cf[j].Comments + } + sort.Slice(cf, sortFunc) } -func (cf ClocFiles) Less(i, j int) bool { - if cf[i].Code == cf[j].Code { - return cf[i].Name < cf[j].Name + +func (cf ClocFiles) SortByBlanks() { + sortFunc := func(i, j int) bool { + if cf[i].Blanks == cf[j].Blanks { + return cf[i].Code > cf[j].Code + } + return cf[i].Blanks > cf[j].Blanks + } + sort.Slice(cf, sortFunc) +} + +func (cf ClocFiles) SortByCode() { + sortFunc := func(i, j int) bool { + return cf[i].Code > cf[j].Code } - return cf[i].Code > cf[j].Code + sort.Slice(cf, sortFunc) } // AnalyzeFile is analyzing file, this function calls AnalyzeReader() inside. diff --git a/language.go b/language.go index a74fcb8..d089a00 100644 --- a/language.go +++ b/language.go @@ -38,17 +38,48 @@ type Language struct { // Languages is an array representation of Language. type Languages []Language -func (ls Languages) Len() int { - return len(ls) +func (ls Languages) SortByName() { + sortFunc := func(i, j int) bool { + return ls[i].Name < ls[j].Name + } + sort.Slice(ls, sortFunc) } -func (ls Languages) Swap(i, j int) { - ls[i], ls[j] = ls[j], ls[i] + +func (ls Languages) SortByFiles() { + sortFunc := func(i, j int) bool { + if len(ls[i].Files) == len(ls[j].Files) { + return ls[i].Code > ls[j].Code + } + return len(ls[i].Files) > len(ls[j].Files) + } + sort.Slice(ls, sortFunc) } -func (ls Languages) Less(i, j int) bool { - if ls[i].Code == ls[j].Code { - return ls[i].Name < ls[j].Name + +func (ls Languages) SortByComments() { + sortFunc := func(i, j int) bool { + if ls[i].Comments == ls[j].Comments { + return ls[i].Code > ls[j].Code + } + return ls[i].Comments > ls[j].Comments + } + sort.Slice(ls, sortFunc) +} + +func (ls Languages) SortByBlanks() { + sortFunc := func(i, j int) bool { + if ls[i].Blanks == ls[j].Blanks { + return ls[i].Code > ls[j].Code + } + return ls[i].Blanks > ls[j].Blanks + } + sort.Slice(ls, sortFunc) +} + +func (ls Languages) SortByCode() { + sortFunc := func(i, j int) bool { + return ls[i].Code > ls[j].Code } - return ls[i].Code > ls[j].Code + sort.Slice(ls, sortFunc) } var reShebangEnv = regexp.MustCompile(`^#! *(\S+/env) ([a-zA-Z]+)`)