Repository: daixiang0/gci
Pull request #210 (2024-07-07 15:31:01)

Add flag to allow multiple prefix() sections to not be automatically sorted
Add a command-line flag that, when enabled, skips sorting "prefix(" imports lexically, while still preserving the default sorting for other types of sections. By default the value is false so as to not change the default behavior of gci. 

Fixes: https://github.com/daixiang0/gci/issues/205

DanWlker: @daixiang0 Force pushed to sign commits, let me know if any additional changes are required. Thanks
daixiang0: Please fix DCO then we can make it land.

Patch:
diff --git a/cmd/gci/gcicommand.go b/cmd/gci/gcicommand.go
index 7279ccf..1d80a85 100644
--- a/cmd/gci/gcicommand.go
+++ b/cmd/gci/gcicommand.go
@@ -12,7 +12,7 @@ import (
 type processingFunc = func(args []string, gciCfg config.Config) error
 
 func (e *Executor) newGciCommand(use, short, long string, aliases []string, stdInSupport bool, processingFunc processingFunc) *cobra.Command {
-	var noInlineComments, noPrefixComments, skipGenerated, skipVendor, customOrder, debug *bool
+	var noInlineComments, noPrefixComments, skipGenerated, skipVendor, customOrder, noLexOrder, debug *bool
 	var sectionStrings, sectionSeparatorStrings *[]string
 	cmd := cobra.Command{
 		Use:               use,
@@ -28,6 +28,7 @@ func (e *Executor) newGciCommand(use, short, long string, aliases []string, stdI
 				SkipGenerated:    *skipGenerated,
 				SkipVendor:       *skipVendor,
 				CustomOrder:      *customOrder,
+				NoLexOrder:       *noLexOrder,
 			}
 			gciCfg, err := config.YamlConfig{Cfg: fmtCfg, SectionStrings: *sectionStrings, SectionSeparatorStrings: *sectionSeparatorStrings}.Parse()
 			if err != nil {
@@ -61,6 +62,7 @@ localmodule: localmodule section, contains all imports from local packages`
 	skipVendor = cmd.Flags().Bool("skip-vendor", false, "Skip files inside vendor directory")
 
 	customOrder = cmd.Flags().Bool("custom-order", false, "Enable custom order of sections")
+	noLexOrder = cmd.Flags().Bool("no-lex-order", false, "Drops lexical ordering for custom sections")
 	sectionStrings = cmd.Flags().StringArrayP("section", "s", section.DefaultSections().String(), sectionHelp)
 
 	// deprecated
diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go
index 85a89e8..5685ac2 100644
--- a/pkg/analyzer/analyzer.go
+++ b/pkg/analyzer/analyzer.go
@@ -142,6 +142,10 @@ func generateCmdLine(cfg config.Config) string {
 		result += " --custom-order "
 	}
 
+	if cfg.BoolConfig.NoLexOrder {
+		result += " --no-lex-order"
+	}
+
 	for _, s := range cfg.Sections.String() {
 		result += fmt.Sprintf(" --Section \"%s\" ", s)
 	}
diff --git a/pkg/config/config.go b/pkg/config/config.go
index cc43f2f..814201a 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -26,6 +26,7 @@ type BoolConfig struct {
 	SkipGenerated    bool `yaml:"skipGenerated"`
 	SkipVendor       bool `yaml:"skipVendor"`
 	CustomOrder      bool `yaml:"customOrder"`
+	NoLexOrder       bool `yaml:"noLexOrder"`
 }
 
 type Config struct {
@@ -63,10 +64,11 @@ func (g YamlConfig) Parse() (*Config, error) {
 		sort.Slice(sections, func(i, j int) bool {
 			sectionI, sectionJ := sections[i].Type(), sections[j].Type()
 
-			if strings.Compare(sectionI, sectionJ) == 0 {
-				return strings.Compare(sections[i].String(), sections[j].String()) < 0
+			if g.Cfg.NoLexOrder || strings.Compare(sectionI, sectionJ) != 0 {
+				return defaultOrder[sectionI] < defaultOrder[sectionJ]
 			}
-			return defaultOrder[sectionI] < defaultOrder[sectionJ]
+
+			return strings.Compare(sections[i].String(), sections[j].String()) < 0
 		})
 	}
 


Test patch:
diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go
index 7a29949..9a41d5d 100644
--- a/pkg/config/config_test.go
+++ b/pkg/config/config_test.go
@@ -29,3 +29,16 @@ func TestParseCustomOrder(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, section.SectionList{section.Default{}, section.Custom{Prefix: "github/daixiang0/gci"}, section.Custom{Prefix: "github/daixiang0/gai"}}, gciCfg.Sections)
 }
+
+func TestParseNoLexOrder(t *testing.T) {
+	cfg := YamlConfig{
+		SectionStrings: []string{"prefix(github/daixiang0/gci)", "prefix(github/daixiang0/gai)", "default"},
+		Cfg: BoolConfig{
+			NoLexOrder: true,
+		},
+	}
+
+	gciCfg, err := cfg.Parse()
+	assert.NoError(t, err)
+	assert.Equal(t, section.SectionList{section.Default{}, section.Custom{Prefix: "github/daixiang0/gci"}, section.Custom{Prefix: "github/daixiang0/gai"}}, gciCfg.Sections)
+}