-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement customizable formatting (#43)
* Update standardPackages for Go 1.17.5 Signed-off-by: Norman Gehrsitz <[email protected]> * Update Go version Signed-off-by: Norman Gehrsitz <[email protected]> * Implement configurable Section based formatting logic. The CLI has been built with Cobra in a backwards compatible manner. Signed-off-by: Norman Gehrsitz <[email protected]> * Add tests for file reformatting Signed-off-by: Norman Gehrsitz <[email protected]> * Add test for skipping over malformed files Signed-off-by: Norman Gehrsitz <[email protected]>
- Loading branch information
Showing
104 changed files
with
3,316 additions
and
531 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package gci | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
func subCommandOrGoFileCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { | ||
var commandAliases []string | ||
for _, subCmd := range cmd.Commands() { | ||
commandAliases = append(commandAliases, subCmd.Name()) | ||
commandAliases = append(commandAliases, subCmd.Aliases...) | ||
} | ||
for _, subCmdStr := range commandAliases { | ||
if strings.HasPrefix(subCmdStr, toComplete) { | ||
// completion for commands is already provided by cobra | ||
// do not return file completion | ||
return []string{}, cobra.ShellCompDirectiveNoFileComp | ||
} | ||
} | ||
return goFileCompletion(cmd, args, toComplete) | ||
} | ||
func goFileCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { | ||
return []string{"go"}, cobra.ShellCompDirectiveFilterFileExt | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package gci | ||
|
||
import ( | ||
"github.com/daixiang0/gci/pkg/gci" | ||
) | ||
|
||
// diffCmd represents the diff command | ||
func (e *Executor) initDiff() { | ||
e.newGciCommand( | ||
"diff path...", | ||
"Prints a git style diff to STDOUT", | ||
"Diff prints a patch in the style of the diff tool that contains the required changes to the file to make it adhere to the specified formatting.", | ||
[]string{}, | ||
true, | ||
gci.DiffFormattedFiles) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package gci | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/daixiang0/gci/pkg/configuration" | ||
"github.com/daixiang0/gci/pkg/constants" | ||
"github.com/daixiang0/gci/pkg/gci" | ||
sectionsPkg "github.com/daixiang0/gci/pkg/gci/sections" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
type processingFunc = func(args []string, gciCfg gci.GciConfiguration) error | ||
|
||
func (e *Executor) newGciCommand(use, short, long string, aliases []string, stdInSupport bool, processingFunc processingFunc) *cobra.Command { | ||
var noInlineComments, noPrefixComments, debug *bool | ||
var sectionStrings, sectionSeparatorStrings *[]string | ||
cmd := cobra.Command{ | ||
Use: use, | ||
Aliases: aliases, | ||
Short: short, | ||
Long: long, | ||
ValidArgsFunction: goFileCompletion, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
fmtCfg := configuration.FormatterConfiguration{*noInlineComments, *noPrefixComments, *debug} | ||
gciCfg, err := gci.GciStringConfiguration{fmtCfg, *sectionStrings, *sectionSeparatorStrings}.Parse() | ||
if err != nil { | ||
return err | ||
} | ||
return processingFunc(args, *gciCfg) | ||
}, | ||
} | ||
if !stdInSupport { | ||
cmd.Args = cobra.MinimumNArgs(1) | ||
} | ||
|
||
// register command as subcommand | ||
e.rootCmd.AddCommand(&cmd) | ||
|
||
sectionHelp := "Sections define how inputs will be processed. " + | ||
"Section names are case-insensitive and may contain parameters in (). " + | ||
fmt.Sprintf("A section can contain a Prefix and a Suffix section which is delimited by %q. ", constants.SectionSeparator) + | ||
"These sections can be used for formatting and will only be rendered if the main section contains an entry." + | ||
"\n" + | ||
sectionsPkg.SectionParserInst.SectionHelpTexts() | ||
// add flags | ||
debug = cmd.Flags().BoolP("debug", "d", false, "Enables debug output from the formatter") | ||
noInlineComments = cmd.Flags().Bool("NoInlineComments", false, "Drops inline comments while formatting") | ||
noPrefixComments = cmd.Flags().Bool("NoPrefixComments", false, "Drops comment lines above an import statement while formatting") | ||
sectionStrings = cmd.Flags().StringSliceP("Section", "s", gci.DefaultSections().String(), sectionHelp) | ||
sectionSeparatorStrings = cmd.Flags().StringSliceP("SectionSeparator", "x", gci.DefaultSectionSeparators().String(), "SectionSeparators are inserted between Sections") | ||
return &cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package gci | ||
|
||
import ( | ||
"github.com/daixiang0/gci/pkg/gci" | ||
) | ||
|
||
// printCmd represents the print command | ||
func (e *Executor) initPrint() { | ||
e.newGciCommand( | ||
"print path...", | ||
"Outputs the formatted file to STDOUT", | ||
"Print outputs the formatted file. If you want to apply the changes to a file use write instead!", | ||
[]string{"output"}, | ||
true, | ||
gci.PrintFormattedFiles) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package gci | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/daixiang0/gci/pkg/configuration" | ||
"github.com/daixiang0/gci/pkg/gci" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
type Executor struct { | ||
rootCmd *cobra.Command | ||
diffMode *bool | ||
writeMode *bool | ||
localFlags *[]string | ||
} | ||
|
||
func NewExecutor(version string) *Executor { | ||
e := Executor{} | ||
rootCmd := cobra.Command{ | ||
Use: "gci [-diff | -write] [-local localPackageURLs] path...", | ||
Short: "Gci controls golang package import order and makes it always deterministic", | ||
Long: "Gci enables automatic formatting of imports in a deterministic manner" + | ||
"\n" + | ||
"If you want to integrate this as part of your CI take a look at golangci-lint.", | ||
ValidArgsFunction: subCommandOrGoFileCompletion, | ||
Args: cobra.MinimumNArgs(1), | ||
Version: version, | ||
RunE: e.runInCompatibilityMode, | ||
} | ||
e.rootCmd = &rootCmd | ||
e.diffMode = rootCmd.Flags().BoolP("diff", "d", false, "display diffs instead of rewriting files") | ||
e.writeMode = rootCmd.Flags().BoolP("write", "w", false, "write result to (source) file instead of stdout") | ||
e.localFlags = rootCmd.Flags().StringSliceP("local", "l", []string{}, "put imports beginning with this string after 3rd-party packages, separate imports by comma") | ||
e.initDiff() | ||
e.initPrint() | ||
e.initWrite() | ||
return &e | ||
} | ||
|
||
// Execute adds all child commands to the root command and sets flags appropriately. | ||
// This is called by main.main(). It only needs to happen once to the rootCmd. | ||
func (e *Executor) Execute() error { | ||
return e.rootCmd.Execute() | ||
} | ||
|
||
func (e *Executor) runInCompatibilityMode(cmd *cobra.Command, args []string) error { | ||
// Workaround since the Deprecation message in Cobra can not be printed to STDERR | ||
_, _ = fmt.Fprintln(os.Stderr, "Using the old parameters is deprecated, please use the named subcommands!") | ||
|
||
if *e.writeMode && *e.diffMode { | ||
return fmt.Errorf("diff and write must not be specified at the same time") | ||
} | ||
// generate section specification from old localFlags format | ||
sections := gci.LocalFlagsToSections(*e.localFlags) | ||
sectionSeparators := gci.DefaultSectionSeparators() | ||
cfg := gci.GciConfiguration{configuration.FormatterConfiguration{false, false, false}, sections, sectionSeparators} | ||
if *e.writeMode { | ||
return gci.WriteFormattedFiles(args, cfg) | ||
} | ||
if *e.diffMode { | ||
return gci.DiffFormattedFiles(args, cfg) | ||
} | ||
return gci.PrintFormattedFiles(args, cfg) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package gci | ||
|
||
import ( | ||
"github.com/daixiang0/gci/pkg/gci" | ||
) | ||
|
||
// writeCmd represents the write command | ||
func (e *Executor) initWrite() { | ||
e.newGciCommand( | ||
"write path...", | ||
"Formats the specified files in-place", | ||
"Write modifies the specified files in-place", | ||
[]string{"overwrite"}, | ||
false, | ||
gci.WriteFormattedFiles) | ||
} |
Oops, something went wrong.