package format import ( "fmt" "sort" "strings" ) type importItem struct { Comment string Name string Path string } func (ii importItem) String() string { var comment string if ii.Comment != "" { comment = ii.Comment + "\n\t" } var name string if ii.Name != "" { name = ii.Name + " " } return comment + name + ii.Path } type importBlock struct { Stdlib []importItem Module []importItem Other []importItem } func importItemSlice(ii []importItem) []string { iis := make([]string, 0, len(ii)) for _, i := range ii { iis = append(iis, i.String()) } return iis } func (i importBlock) String() string { var decl strings.Builder decl.WriteString(strings.Join(importItemSlice(i.Stdlib), "\n\t")) if len(i.Stdlib) > 0 { decl.WriteString("\n\n\t") } decl.WriteString(strings.Join(importItemSlice(i.Module), "\n\t")) if len(i.Module) > 0 { decl.WriteString("\n\n\t") } decl.WriteString(strings.Join(importItemSlice(i.Other), "\n\t")) return fmt.Sprintf(`import ( %s )`, decl.String()) } func parseBlock(module string, imports []string) importBlock { var block importBlock var comment string for _, imp := range imports { if imp == "" { continue } i := imp if strings.HasPrefix(i, `//`) { var nl string if comment != "" { nl = "\n" } comment = nl + i continue } var name string if !strings.HasPrefix(i, `"`) { parts := strings.SplitN(i, " ", 2) name = parts[0] i = parts[1] } item := importItem{ Comment: comment, Name: name, Path: i, } switch { case strings.Contains(i, module): block.Module = append(block.Module, item) case strings.Contains(i, "."): block.Other = append(block.Other, item) default: block.Stdlib = append(block.Stdlib, item) } comment = "" } fn := func(ii []importItem) func(int, int) bool { return func(i, j int) bool { return ii[i].Path < ii[j].Path } } sort.Slice(block.Stdlib, fn(block.Stdlib)) sort.Slice(block.Module, fn(block.Module)) sort.Slice(block.Other, fn(block.Other)) return block }