formattable 0.2.0

Ergonomically support formatted output
Documentation
# `formattable`

Make it easy and ergonomic to provide formatted output.

[`Format`] is an enum that allows selecting a particular format, but supports
standard methods for serializing content. This makes it convenient to select a
user-selected serializer at runtime.

For usage with [clap](https://docs.rs/clap/latest/clap/), we also provide
[`FormatArg`] and [`FormatArgOpt`] which standardizes the flags and parsing for
selecting a serializer.

## Usage

Make sure you enable/disable the appropriate [features](#features) for the functionality
you want.

### Basic

```rust
use formattable::Format;
use serde::Serialize;

// Have some data structure that can be serialized.
#[derive(Serialize)]
struct Foo;

// Instantiate a Format variant. Format is Copy, so it's easy to use and pass
// around.
let fmt = Format::Json;

// Write your data structure to a JSON string.
let foo = Foo;
fmt.to_string(&foo).unwrap();
```

### `clap` Integration \[feature: clap\]

```rust
use clap::Parser;
use formattable::Format;
use serde::Serialize;

/// Demonstrate how to use [`Format`] in a `clap`-based CLI.
///
/// This example just dumps the CLI arguments themselves as the selected format.
#[derive(Debug, Parser, Serialize)]
struct Cli {
    /// Select a format for output.
    #[clap(short, long, value_enum, default_value_t = Format::Json)]
    format: Format,
}

fn main() {
    let cli = Cli::parse();

    println!("{}", cli.format.to_string(&cli).unwrap());
}
```

### Flattened `clap` Integration \[feature: clap\]

The easiest way to consistently integrate [`Format`] with clap is to use
[`FormatArg`], which implements
[`clap::Args`](https://docs.rs/clap/latest/clap/trait.Args.html):

```rust
use clap::Parser;
use formattable::FormatArg;
use serde::Serialize;

/// Demonstrate how to use `formattable` in a `clap`-based CLI.
///
/// This example just dumps the CLI arguments themselves as the selected format.
#[derive(Debug, Parser, Serialize)]
struct Cli {
    #[clap(flatten)]
    format: FormatArg,
}

fn main() {
    let cli = Cli::parse_from(["", "-f", "json"]);

    println!("{}", cli.format.to_string_pretty(&cli).unwrap());
}
```

## Features

* `default` [toml, json, yaml]
* `clap` - enables the `clap` CLI integration
* `json` - default; enables serialization to JSON
* `yaml` - default; enables serialization to YAML
* `toml` - default; enables serialization to TOML

## Roadmap

There's no concrete roadmap or plans, but general ideas that would be
interesting to implement include:

* Use a macro to remove the boilerplate around the [`FormatArg`] and
  [`FormatArgOpt`] struct definitions and implementations;
* Instead of providing dedicated argument types, provide a macro that can be
  used to add format support to structs;
* Add support for a default format. This would be relatively easy if
  functionality was provided via macro;
* Figure out some way to have text be a selectable format.