keep-sorted Documentation
repository·main·Indexed 18 days ago
https://github.com/google/keep-sortedA language-agnostic tool designed to sort lines located between specific comment-delimited markers (keep-sorted start and keep-sorted end) within a file. It supports nested blocks, custom sorting logic via RE2 regular expressions, numeric sorting, and integration with pre-commit. The tool provides two primary CLI modes: 'fix' to automatically sort content and 'lint' to check for unsorted blocks.
What's inside keep-sorted
- keep-sorted is a language-agnostic formatter designed to sort lines located between two specific markers within a larger file. It is useful for maintaining alphabetical order in lists, imports, or configuration blocks while leaving the rest of the file untouched.
Ignore prefixes during sorting
mainUse
ignore_prefixes=prefix1,prefix2to exclude specific prefixes from the sorting logic. If a line starts with one of these prefixes, it is treated as an empty string for sorting purposes.+// keep-sorted start ignore_prefixes=fs.setBoolFlag,fs.setIntFlag fs.setBoolFlag("paws_with_cute_toebeans", true) fs.setIntFlag("pretty_whiskered_kitten", 6) fs.setBoolFlag("whiskered_adorable_dog", true) // keep-sorted endConfigure post-sorting formatting
mainAdjust the output appearance after sorting:
remove_duplicates=no: By default,keep-sortedremoves duplicate lines. Set tonoto preserve them. Note that duplicates with different attached comments are preserved by default.newline_separated=N: Adds blank lines between sorted items. Usenewline_separated=yesfor one blank line, ornewline_separated=Nfor $N$ blank lines.
+# keep-sorted start remove_duplicates=no rotation: bar rotation: bar rotation: baz # keep-sorted end+# keep-sorted start newline_separated=2 Apples Bananas # keep-sorted endSkip lines at the start or end of a block
mainUse
skip_linesto prevent specific lines from being included in the sort, such as table headers or footers.- A positive value skips lines at the start of the sorted region.
- A negative value skips lines at the end of the sorted region.
Example:
skip_lines=2,-2skips the first 2 lines and the last 2 lines of the block.+<!-- keep-sorted start skip_lines=2,-2 --> Item | Cost ----- | ----- Apple | $1.09 Lemon | $1.50 ----- | ----- Total | $4.69 +<!-- keep-sorted end -->Manage sticky comments and prefixes
mainBy default, comments embedded in a sorted block stick to their successor. The comment must use the same marker as the
keep-sortedinstruction (e.g.,#for# keep-sorted start).Supported markers:
//,/*,#,--,;, and<!--.- Disable sticky comments: Use
sticky_comments=noto prevent comments from moving with the lines they precede. - Custom sticky prefixes: Use
sticky_prefixes=prefix1,prefix2to make other specific prefixes stick to their successors. Prefixes cannot contain spaces.
+# keep-sorted start sticky_comments=no # alice # bob # charlie username: al1 username: bo2 username: ch3 # keep-sorted end+// keep-sorted start sticky_prefixes=/*,@Annotation Baz baz; /* Foo */ @Annotation Foo foo; // keep-sorted end- Disable sticky comments: Use
How to use keep-sorted markers in files
mainTo define a block of text for
keep-sortedto manage, surround the lines withkeep-sorted startandkeep-sorted endmarkers inside comments. The markers must match the comment syntax of the language you are using (e.g.,//for Java,#for Python).keep-sortedalso supports nested blocks, allowing you to sort multiple independent lists within a single larger sorted block.@Component( modules = { // keep-sorted start AuthModule.class, GetRequestModule.class, LoggingModule.class, // keep-sorted end })How keep-sorted handles whitespace and indentation
mainkeep-sorted aims to mimic human sorting behavior regarding whitespace:
- Indentation: With the default
group=yessetting, lines with increasing indentation are grouped together during sorting. - Leading Whitespace: Leading whitespace is ignored when comparing strings for sorting order.
- Trailing Newlines: keep-sorted preserves any number of trailing newlines at the end of a block; it will not remove them.
- Internal Linebreaks: Non-trailing linebreaks (linebreaks within the content) are moved to the beginning of the content block. If
remove_duplicates=yesis set, these moved linebreaks are deduplicated.
- Indentation: With the default
Group lines using prefixes or regex
mainYou can define group boundaries using prefixes or regular expressions:
- Prefix grouping: Use
group_prefixes=prefix1,prefix2to treat any line starting with these prefixes as a continuation of the previous line. - Regex-delimited grouping: Use
group_start_regexorgroup_end_regexwith RE2 regular expressions.group_start_regex: The matching line starts a new group.group_end_regex: The matching line ends the current group.- These options are mutually exclusive.
- Use
newline_separated=yesif the regex should trigger based on line breaks.
+// keep-sorted start group_prefixes=and,with hamburger with lettuce and tomatoes peanut butter and jelly spaghetti with meatballs +// keep-sorted end+// keep-sorted start group_start_regex=["^define\\b"] newline_separated=yes // Some other comment for bar define bar = ghi + jkl; // Some comment for foo define foo = abc + def; +// keep-sorted end- Prefix grouping: Use
How keep-sorted handles trailing commas in lists
mainkeep-sorted attempts to handle commas
// Input: 3, 1, 2 // Output: 1, 2, 3,Configure sorting behavior (Case, Numeric, Regex, Order)
mainControl how the logical lines are ordered using these options:
case=no: Sort case-insensitively (default is case-sensitive).numeric=yes: Interpret sequences of digits as numeric values rather than lexical strings.by_regex=...: Sort based on the results of RE2 regular expressions. If capturing groups are used, only the captured text is used for sorting.- Note:
.matches\nby default (addssflag). Use(?-s)to disable.
- Note:
order=desc: Sort in descending order (default is ascending).prefix_order=p1,p2,...: Define a custom order for lines starting with specific prefixes. Unmatched lines are placed after matched ones. Use an empty prefix (,,) to place unmatched lines between specific prefixes.
+# keep-sorted start case=no alpha Bravo charlie Delta echo Foxtrot # keep-sorted end+# keep-sorted start numeric=yes 'PROGRESS_1_PERCENT', 'PROGRESS_5_PERCENT', 'PROGRESS_10_PERCENT', 'PROGRESS_50_PERCENT', 'PROGRESS_100_PERCENT', # keep-sorted end+// keep-sorted start prefix_order=INIT_,,FINAL_ INIT_BAR, INIT_FOO, DO_SOMETHING_WITH_BAR, DO_SOMETHING_WITH_FOO, FINAL_BAR, FINAL_FOO // keep-sorted endConfigure line continuation and block grouping
mainPre-sorting options define what constitutes a single logical line.
- Line continuations: By default, increasing indentation groups lines with the line above. Disable this using
group=no. - Blocks: Use
block=yesto handle complex structures like Go structs or JSON objects. It identifies groups by balancing typical symbols (parentheses, braces, brackets, and quotes).
Warning:
keep-sortedis not language-aware; it sorts groups as basic strings. Mixing line breaks and whitespace may cause unexpected results. Angle brackets (<and>) are not supported in block mode.Note: Braces inside string literals (starting/ending with
',''',",""", or`) are ignored for balancing.+// keep-sorted start group=no new Baz() private final Bar bar; private final Baz baz = private final Foo foo; // keep-sorted endwidgets := []widget{ + // keep-sorted start block=yes { Name: "abc", }, { Name: "def", }, + // keep-sorted end }- Line continuations: By default, increasing indentation groups lines with the line above. Disable this using
Install keep-sorted
mainTo install
keep-sorted, you must first have Go installed (version 1.23 or later is required). Use the following command to install the tool viago install:go install github.com/google/keep-sorted@v0.9.1