Creating an Organized Collection of Sorted Text Lists

Published on
Authors

I am a big fan of storing data in text files. I have a lot of text files that contain lists of things. I have lists of books I have read or want to read, lists of movies I want to watch, lists of places I want to visit, and so on. Having so many lists can be hard to manage and keep organized so I created a tool to help me with that. This tool "scopedsort" is a feature rich text sorter that takes indentation into account.

Indentation Awareness

Most text sorters sort lines based on their lexicographical order. This is a problem when you have lists of items that are indented. Example:

# input.txt
- Games
  - Valorant
  - League of Legends
- Music
- Apps
# expected.txt
- Apps
- Games
  - League of Legends
  - Valorant
- Music
# actual.txt
  - League of Legends
  - Valorant
- Apps
- Games
- Music

This tool fixes this by being aware of the indentation of the lines and only sorting within the same level of indentation.

Sort Comments

In addition to wanting to have indention aware sorting, I also wanted to be able to sort this text file with a single command line invocation. This is doable with something like the standard unix tool: sort input.txt but this will not work if you have surrounding text that you want to keep unchanged. Example:

# input.txt
My favorite games:

- League of Legends
- Valorant

I also like listening to music.
# output.txt

- League of Legends
- Valorant
I also like listening to music.
My favorite games:

Which is obviously not what we want. We need to define a section we want to sort somehow, and if we are going to do this over and over, it would be nice to have it baked into the text. This is where "sort comments" come in:

// { sort-start --regex /['"]/ }
import react from 'react'
import express from 'express'
import isIsOdd from 'is-is-odd'
// { sort-end }

We mark the start of the section with a line that has the text { sort-start } somewhere in the line. In between the ending curling bracket, we can include arguments on what and how to sort. For this example, we have made it so it sorts by the name of the import alphabetically. If we ever add another import, we can simply call the sort function and it will sort it for us, without us having to specify what or how to sort. To end a section, we need a the line { sort-end }.

Another example:

favorite.txt
My favorite movies are:

// { sort-start --reverse }
- The Dark Knight
- Inception
- Interstellar
// { sort-end }

My favorite shows are:

// { sort-start --unique }
- Breaking Bad
- Breaking Bad
- Game of Thrones
- The Office
//  { sort-end }

Now we can just call ssort --use-sort-comments --modify favorites.txt and it will sort only the sort comment sections.

Extensive Options

This project has a lot of options; all of which can be used together (provided they don't conflict logically). Other tools have a reasonable amount of options, but usually they don't provide a nice way to combine them.

Here are all the sorters (you can only have one):

  • Default (Lexicographical)
  • Case Insensitive
  • Numerical
  • Natural
  • Float
  • By Month
  • By Day
  • By Length
  • Random

You can also have multiple modifiers:

  • Reverse
  • Unique
  • Recursive
  • Markdown (take into account markdown list syntax)

Finally you can have item searches to specify what specifically to sort by:

  • By Regex
  • By Column (this column can also use any of the sorters)
  • Unique Sort Order (e.g. b,a,d,c)

Some of the more extensive options this program implements include: custom-sort-orders, sort-by-column, sort-by-regex, etc…

Other Examples

Removing Duplicates + Reverse

  • unique = "exact"
  • reverse = true
- Hot Dog
- Burger
- Salad
- Burger
- Sandwhich
- Sandwhich
- Salad
- Hot Dog
- Burger

Switch Inner Case Statements

  • no options

This is an example of how this program's indentation awareness works.

Note: the content actually being sorted is highlighted, the non-highlighted lines are just there for visual aid.

switch (name) {
  case 'max':
    console.log('max')
    break
  case 'sam':
    console.log('sam')
    break
  case 'ava':
    console.log('ava')
    break
  case 'edna':
    console.log('edna')
    break
}
switch (name) {
  case 'ava':
    console.log('ava')
    break
  case 'edna':
    console.log('edna')
    break
  case 'max':
    console.log('max')
    break
  case 'sam':
    console.log('sam')
    break
}

Section Starter HTML

This in example which show's the possibilities of section-starter.

Note: the content actually being sorted is highlighted, the non-highlighted lines are just there for visual aid.

  • section-starter = /^\t<div/
<div>
  <div class="child">
    <h3>Zachary Garrett</h3>
    <p>Computer Science</p>
    <div class="something">lorem ipsum</div>
  </div>
  <div class="child">
    <h3>Elijah Tyler</h3>
    <p>Math</p>
    <div class="something">lorem ipsum</div>
  </div>
  <div class="child">
    <h3>Earl Henry</h3>
    <p>Aerospace</p>
    <div class="something">lorem ipsum</div>
  </div>
  <div class="child">
    <h3>Herman Reed</h3>
    <p>English</p>
    <div class="something">lorem ipsum</div>
  </div>
</div>
<div>
  <div class="child">
    <h3>Earl Henry</h3>
    <p>Aerospace</p>
    <div class="something">lorem ipsum</div>
  </div>
  <div class="child">
    <h3>Elijah Tyler</h3>
    <p>Math</p>
    <div class="something">lorem ipsum</div>
  </div>
  <div class="child">
    <h3>Herman Reed</h3>
    <p>English</p>
    <div class="something">lorem ipsum</div>
  </div>
  <div class="child">
    <h3>Zachary Garrett</h3>
    <p>Computer Science</p>
    <div class="something">lorem ipsum</div>
  </div>
</div>

Sort By 2nd Column (CSV)

  • field-separator = ","
  • sort-group = "{2}"
Jake,Lil Peep,30
Niel,The Neighbourhood,12
Max,Arctic Monkeys,72
Jo,AJR,65
Jo,AJR,65
Max,Arctic Monkeys,72
Jake,Lil Peep,30
Niel,The Neighbourhood,12

Sort By 3rd Column (custom)

  • sort-group = "{3}"
  • sort-order = "i:female;non-binary;male;n/a"
Sam    18  Male       140
Jack   23  Non-Binary 120
Niel   16  Female     135
Max    17  Male       135
Jane   22  Female     100
max    17  male       135
Jones  17  male       135
Lydia  N/A N/A        120
Mike   N/A male       N/A
Niel   16  Female     135
Jane   22  Female     100
Jack   23  Non-Binary 120
Sam    18  Male       140
Max    17  Male       135
max    17  male       135
Jones  17  male       135
Mike   N/A male       N/A
Lydia  N/A N/A        120

How to Use

You can use this tool as an npm package, a vscode extension, a command line tool, or just on the web app. Full documentation can be found on the website.