diff --git a/README.md b/README.md index 8794385..a8ef68c 100644 --- a/README.md +++ b/README.md @@ -396,8 +396,11 @@ treated as sticky. These prefixes cannot contain space characters. #### Skipping lines In some cases, it may not be possible to have the start directive on the line -immediately before the sorted region. In this case, `skip_lines` can be used to -indicate how many lines are to be skipped before the sorted region. +immediately before the sorted region or end immediately after. In these cases, +`skip_lines` can be used to indicate how many lines are to be skipped before +and/or after the sorted region. The `skip_lines` option interprets positive +values as lines to skip at the start of the sorted region and negative values +as lines to skip at the end. For instance, this can be used with a Markdown table, to prevent the headers and the dashed line after the headers from being sorted: @@ -435,6 +438,43 @@ Alpha | Foo +This can be used to keep the footers of a table from being sorted as well: + + + + + + +
+ +```md + +Item | Cost +----- | ----- +Lemon | $1.50 +Pear | $2.10 +Apple | $1.09 +----- | ----- +Total | $4.69 + +``` + + + +```diff ++ + Item | Cost + ----- | ----- + Apple | $1.09 + Lemon | $1.50 + Pear | $2.10 + ----- | ----- + Total | $4.69 ++ +``` + +
+ ### Sorting options Sorting options tell keep-sorted how the logical lines in your keep-sorted diff --git a/goldens/simple.err b/goldens/simple.err index 55f1c03..f9353ff 100644 --- a/goldens/simple.err +++ b/goldens/simple.err @@ -1,4 +1,4 @@ -WRN skip_lines has invalid value: -1 line=113 +WRN skip_lines has conflicting values (should one of these be positive, to skip lines at the start of the block instead?): -1,-1 line=113 WRN unrecognized option "foo" line=113 WRN while parsing option "ignore_prefixes": content appears to be an unterminated YAML list: "[abc, foo" line=120 exit status 1 diff --git a/goldens/simple.in b/goldens/simple.in index 9f5988a..b426939 100644 --- a/goldens/simple.in +++ b/goldens/simple.in @@ -110,7 +110,7 @@ B // keep-sorted-test end Invalid option - keep-sorted-test start group=yes skip_lines=-1 foo=bar + keep-sorted-test start group=yes skip_lines=-1,-1 foo=bar 2 1 3 diff --git a/goldens/simple.out b/goldens/simple.out index 7ef981b..5049910 100644 --- a/goldens/simple.out +++ b/goldens/simple.out @@ -111,7 +111,7 @@ C // keep-sorted-test end Invalid option - keep-sorted-test start group=yes skip_lines=-1 foo=bar + keep-sorted-test start group=yes skip_lines=-1,-1 foo=bar 1 2 3 diff --git a/keepsorted/block.go b/keepsorted/block.go index 67f5fe3..35a5148 100644 --- a/keepsorted/block.go +++ b/keepsorted/block.go @@ -113,7 +113,8 @@ func (f *Fixer) newBlocks(filename string, lines []string, offset int, include f warnings = append(warnings, finding(filename, start.index+offset, start.index+offset, warn.Error())) } - start.index += opts.SkipLines + start.index += opts.startOffset() + endIndex += opts.endOffset() if start.index >= endIndex { continue } diff --git a/keepsorted/keep_sorted_test.go b/keepsorted/keep_sorted_test.go index 0d00180..b90cd0b 100644 --- a/keepsorted/keep_sorted_test.go +++ b/keepsorted/keep_sorted_test.go @@ -222,7 +222,7 @@ func TestFindings(t *testing.T) { want: []*Finding{finding(filename, 3, 5, errorUnordered, automaticReplacement(3, 5, "1\n2\n3\n"))}, }, { - name: "SkipLines", + name: "SkipLinesStart", in: ` // keep-sorted-test start skip_lines=2 @@ -235,6 +235,48 @@ func TestFindings(t *testing.T) { want: []*Finding{finding(filename, 5, 7, errorUnordered, automaticReplacement(5, 7, "1\n2\n3\n"))}, }, + { + name: "SkipLinesEnd", + + in: ` +// keep-sorted-test start skip_lines=-2 +5 +4 +3 +2 +1 +// keep-sorted-test end`, + + want: []*Finding{finding(filename, 3, 5, errorUnordered, automaticReplacement(3, 5, "3\n4\n5\n"))}, + }, + { + name: "SkipLinesStartAndEnd", + + in: ` +// keep-sorted-test start skip_lines=1,-1 +5 +4 +3 +2 +1 +// keep-sorted-test end`, + + want: []*Finding{finding(filename, 4, 6, errorUnordered, automaticReplacement(4, 6, "2\n3\n4\n"))}, + }, + { + name: "SkipLinesEndAndStart", + + in: ` +// keep-sorted-test start skip_lines=-1,1 +5 +4 +3 +2 +1 +// keep-sorted-test end`, + + want: []*Finding{finding(filename, 4, 6, errorUnordered, automaticReplacement(4, 6, "2\n3\n4\n"))}, + }, { name: "MismatchedStart", diff --git a/keepsorted/options.go b/keepsorted/options.go index 551f3be..6b5c6fa 100644 --- a/keepsorted/options.go +++ b/keepsorted/options.go @@ -75,6 +75,7 @@ func (opts BlockOptions) String() string { // - []string: key=a,b,c,d // - map[string]bool: key=a,b,c,d // - int: key=123 +// - []int: key=1,-1 // - ByRegexOptions key=a,b,c,d, key=[yaml_list] type blockOptions struct { // AllowYAMLLists determines whether list.set valued options are allowed to be specified by YAML. @@ -85,7 +86,7 @@ type blockOptions struct { /////////////////////////// // SkipLines is the number of lines to ignore before sorting. - SkipLines int `key:"skip_lines"` + SkipLines []int `key:"skip_lines"` // Group determines whether we group lines together based on increasing indentation. Group bool // GroupPrefixes tells us about other types of lines that should be added to a group. @@ -243,6 +244,8 @@ func formatValue(val reflect.Value) (string, error) { } case reflect.TypeFor[int](): return strconv.Itoa(int(val.Int())), nil + case reflect.TypeFor[[]int](): + return formatIntList(val.Interface().([]int)), nil case reflect.TypeFor[[]ByRegexOption](): opts := val.Interface().([]ByRegexOption) vals := make([]string, 0, len(opts)) @@ -301,6 +304,14 @@ func formatList(vals []string) (string, error) { return strings.TrimSpace(string(out)), nil } +func formatIntList(intVals []int) string { + vals := make([]string, 0, len(intVals)) + for _, v := range intVals { + vals = append(vals, strconv.Itoa(v)) + } + return strings.Join(vals, ",") +} + func guessCommentMarker(startLine string) string { startLine = strings.TrimSpace(startLine) for _, marker := range []string{"//", "#", "/*", "--", ";", "