10 releases (breaking)

0.8.0 May 1, 2023
0.7.0 Jul 30, 2022
0.6.1 Jul 21, 2020
0.6.0 Mar 9, 2020

#158 in Value formatting

MIT license

40KB
998 lines

ruut

Run tests Crates.io

Why

I deal with folder structures a lot for work at DocSend. I also love the output of tree(1) for talking about folder structures.

Unfortunately, most of the time I'm not talking about folder structures on my file-system, so in order to get the pretty output with tree(1), I would have to create the directories and/or files on my computer, which seems a bit ridiculous.

That's why I created ruut. It takes a fairly easy-to-type expression like this:

Parent (Child 1, Child 2 (Grandchild 1, Grandchild 2), Child 3)

and turns it into something pretty like

Parent
├── Child 1
├── Child 2
│   ├── Grandchild 1
│   └── Grandchild 2
└── Child 3

It's also good for pretty-printing serialized representations of trees (see the format options below).

NOTE: If you're looking to just render things with that tree style shown above from a Rust program, take a look at render_as_tree.

Usage

ruut can either take the "structure" as an argument or from stdin:

$ ruut 'Parent (Child 1, Child 2 (Grandchild 1, Grandchild 2), Child 3)'
# Equivalent to
$ echo 'Parent (Child 1, Child 2 (Grandchild 1, Grandchild 2), Child 3)' | ruut

Installation

Download from GitHub

Grab the newest published version from the Releases section of this repo.

With cargo

  1. Install rust with rustup
  2. Run cargo install ruut

Formats

All of the examples in this section produce this as an output:

Parent
├── Child 1
├── Child 2
│   ├── Grandchild 1
│   └── Grandchild 2
└── Child 3
    └── Grandchild 3

Parens (-f parens, default)

Parent (Child 1, Child 2 (Grandchild 1, Grandchild 2), Child 3 (Grandchild 3))

This is intended to be easy to type. Note that whitespace in the middle of a folder name is preserved.

Here's a more formal description of the syntax:

<name of folder> [(<name of subfolder 1> [(<name of subsubfolder1>[, <name of
subsubfolder2>[, ...]])][, <name of subfolder 2> [, ...]])]

Surrounding <,> means you fill in those values yourself. Surrounding [,] means that part is optional.

JSON (-f json)

{
  "Parent": {
    "Child 1": null,
    "Child 2": {
      "Grandchild 1": null,
      "Grandchild 2": {},
    },
    "Child 3": {
      "Grandchild 3": "doesn't matter",
    }
  }
}

Only key names are really relevant here. Note that entities other than objects and empty objects are ignored.

Note that all JSON5 syntax is accepted. JSON5 is a superset of JSON with support for different types of quotes, comments, etc., so you can much more easily copy from an actual JavaScript environment. See the JSON5 website for more details.

JSON with properties (-f jsonprop)

{
  "name": "Parent",
  "children": [
    {
      "name": "Child 1"
    },
    { 
      "name": "Child 2",
      "children": [
        {
          "name": "Grandchild 1"
        },
        {
          "name": "Grandchild 2",
          "children": []
        }
      ]
    },
    {
      "name": "Child 3",
      "children": [
        {
          "name": "Grandchild 3",
          "children": null
        }
      ]
    }
  ]
}

This is often useful if you're pulling structured trees from some external source instead of writing them by hand. Note that children can also be an object--in such a case, the properties of that object are iterated over and key names are ignored:

{
  "name": "Parent",
  "children": {
    "whatever_1": {
      "name": "Child 1"
    },
    "whatever_2": { 
      "name": "Child 2",
      "children": {
        "pls_ignore": {
          "name": "Grandchild 1"
        },
        "test_post": {
          "name": "Grandchild 2",
          "children": {}
        }
      }
    },
    "whatever_3": {
      "name": "Child 3",
      "children": {
        "it_me": {
          "name": "Grandchild 3",
          "children": null
        }
      }
    }
  }
}

Note that all JSON5 syntax is accepted. JSON5 is a superset of JSON with support for different types of quotes, comments, etc., so you can much more easily copy from an actual JavaScript environment. See the JSON5 website for more details.

By default, this format looks for the properties name for what to print for each item and children for what items are immediate descendants. To change this, you can use the --template and --children options, respectively. Missing values are filled in with the text <missing>--this can be overridden with the --raise-on-missing flag.

-t/--template <template_str>

This option allows you to grab any properties from each JSON node using a simple curly brace template syntax. E.g. for a node with the properties id = 3, type = "Folder", you could write a template string of Id: {id}, Type: {type} which would result in Id: 3, Type: Folder.

-c/--children <children_prop>

This option allows you to specify the name of the property that contains the children JSON nodes, which is children by default.

-r/--raise-on-missing

This flag will cause ruut to immediately error out if any of the placeholders in the template are missing.

Versioning

This project respects semantic versioning.

Dependencies

~7.5MB
~141K SLoC