Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,47 @@ allows for sorting data such as Go structs and JSON objects.
> Note: angle brackets (`<` and `>`) are not supported by block mode due to
> being used for mathematical expressions in an unbalanced format.

#### Custom grouping

Another way to group lines together is with the `group_prefixes` argument. This
takes a comma-separated list of prefixes. Any line beginning with one of those
prefixes will be treated as a continuation line.

<table border="0">
<tr>
<td>

```

spaghetti
with meatballs
peanut butter
and jelly
hamburger
with lettuce
and tomatoes

```

</td>
<td>

```diff
+// keep-sorted start group_prefixes=and,with
hamburger
with lettuce
and tomatoes
peanut butter
and jelly
spaghetti
with meatballs
+// keep-sorted end
```

</td>
</tr>
</table>

#### Comments

Comments embedded within the sorted block are made to stick with their
Expand Down
22 changes: 22 additions & 0 deletions goldens/skip_lines.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,25 @@ This line should not be sorted.
Charlie | Baz
<!-- keep-sorted-test end -->
<!-- keep-sorted-test end -->

Skip lines with group_prefixes:
// keep-sorted-test start skip_lines=2 group_prefixes=:
| birds |
| ------------ |
| blue footed |
: booby |
| crested |
: bobwhite |
| anhinga |
// keep-sorted-test end

Skip lines with group_prefixes indented:
// keep-sorted-test start skip_lines=2 group_prefixes=:
| birds |
| ------------ |
| blue footed |
: booby |
| crested |
: bobwhite |
| anhinga |
// keep-sorted-test end
22 changes: 22 additions & 0 deletions goldens/skip_lines.out
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,25 @@ This line should not be sorted.
Bravo | Foxtrot
<!-- keep-sorted-test end -->
<!-- keep-sorted-test end -->

Skip lines with group_prefixes:
// keep-sorted-test start skip_lines=2 group_prefixes=:
| birds |
| ------------ |
| anhinga |
| blue footed |
: booby |
| crested |
: bobwhite |
// keep-sorted-test end

Skip lines with group_prefixes indented:
// keep-sorted-test start skip_lines=2 group_prefixes=:
| birds |
| ------------ |
| anhinga |
| blue footed |
: booby |
| crested |
: bobwhite |
// keep-sorted-test end
37 changes: 37 additions & 0 deletions keepsorted/keep_sorted_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ var (
Lint: true,
SkipLines: 0,
Group: true,
GroupPrefixes: nil,
IgnorePrefixes: nil,
Numeric: false,
StickyComments: true,
Expand Down Expand Up @@ -1266,6 +1267,33 @@ func TestLineGrouping(t *testing.T) {
}},
},
},
{
name: "Group_Prefixes",
opts: defaultOptionsWith(func(opts *blockOptions) {
opts.GroupPrefixes = map[string]bool{"and": true, "with": true}
opts.Block = false
}),

want: []lineGroup{
{nil, []string{
"peanut butter",
"and jelly",
}},
{nil, []string{
"spaghetti",
"with meatballs",
}},
{nil, []string{
"hamburger",
" with lettuce",
" and tomatoes",
"and cheese",
}},
{nil, []string{
"dogs and cats",
}},
},
},
{
name: "Group_UnindentedNewlines",
opts: defaultOptionsWith(func(opts *blockOptions) {
Expand Down Expand Up @@ -1567,6 +1595,15 @@ func TestBlockOptions(t *testing.T) {
opts.IgnorePrefixes = []string{"a", "b", "c", "d"}
}),
},
{
name: "GroupPrefixesRequiresGrouping",
in: "// keep-sorted-test group_prefixes=a,b,c group=no",

want: defaultOptionsWith(func(opts *blockOptions) {
opts.Group = false
}),
wantErr: "group_prefixes may not be used with group=no",
},
{
name: "ignore_prefixes_ChecksLognestPrefixesFirst",
in: "// keep-sorted-test ignore_prefixes=DoSomething(,DoSomething({",
Expand Down
2 changes: 2 additions & 0 deletions keepsorted/line_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ func groupLines(lines []string, metadata blockMetadata) []lineGroup {
appendLine(i, l)
} else if metadata.opts.Group && (!lineRange.empty() && initialIndent != nil && indents[i] > *initialIndent || numUnmatchedStartDirectives > 0) {
appendLine(i, l)
} else if metadata.opts.Group && metadata.opts.hasGroupPrefix(l) {
appendLine(i, l)
} else if metadata.opts.hasStickyPrefix(l) {
if !lineRange.empty() {
finishGroup()
Expand Down
26 changes: 23 additions & 3 deletions keepsorted/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ type blockOptions struct {
SkipLines int `key:"skip_lines"`
// Group determines whether we group lines together based on increasing indentation.
Group bool `default:"true"`
// GroupPrefixes tells us about other types of lines that should be added to a group.
GroupPrefixes map[string]bool `key:"group_prefixes"`
// Block opts us into a more complicated algorithm to try and understand blocks of code.
Block bool `default:"false"`
// StickyComments tells us to attach comments to the line immediately below them while sorting.
Expand Down Expand Up @@ -114,6 +116,11 @@ func (f *Fixer) parseBlockOptions(startLine string) (blockOptions, error) {
ret.SkipLines = 0
}

if ret.GroupPrefixes != nil && !ret.Group {
errs = errors.Join(errs, fmt.Errorf("group_prefixes may not be used with group=no"))
ret.GroupPrefixes = nil
}

if cm := f.guessCommentMarker(startLine); cm != "" {
ret.commentMarker = cm
if ret.StickyComments {
Expand Down Expand Up @@ -216,17 +223,30 @@ func (f *Fixer) guessCommentMarker(startLine string) string {
return ""
}

// hasStickyPrefix determines if s has one of the StickyPrefixes.
func (opts blockOptions) hasStickyPrefix(s string) bool {
// hasPrefix determines if s has one of the prefixes.
func hasPrefix(s string, prefixes map[string]bool) bool {
if len(prefixes) == 0 {
return false
}
s = strings.TrimLeftFunc(s, unicode.IsSpace)
for p := range opts.StickyPrefixes {
for p := range prefixes {
if strings.HasPrefix(s, p) {
return true
}
}
return false
}

// hasStickyPrefix determines if s has one of the StickyPrefixes.
func (opts blockOptions) hasStickyPrefix(s string) bool {
return hasPrefix(s, opts.StickyPrefixes)
}

// hasGroupPrefix determines if s has one of the GroupPrefixes.
func (opts blockOptions) hasGroupPrefix(s string) bool {
return hasPrefix(s, opts.GroupPrefixes)
}

// removeIgnorePrefix removes the first matching IgnorePrefixes from s, if s
// matches one of the IgnorePrefixes.
func (opts blockOptions) removeIgnorePrefix(s string) (string, bool) {
Expand Down