config-easy
config-easy is a small Rust crate for displaying and editing key/value settings in command-line applications.
The core crate is storage-agnostic. It can be used with any settings backend by implementing SettingsStore. A built-in rusqlite adapter is available behind the optional rusqlite feature.
Applications remain responsible for schema creation, default values, typed configuration structs, CLI parsing, and app-specific behavior.
Install
For custom storage or to avoid database dependencies:
[]
= "0.2"
For the built-in SQLite adapter:
[]
= { = "0.2", = ["rusqlite"] }
= "0.40"
Default features are empty, so config-easy does not pull in rusqlite unless requested.
SQLite Usage
The SQLite adapter expects a table with key/value text columns. The default schema is:
(
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
Basic usage:
let connection = open?;
run?;
This uses:
- table:
settings - key column:
key - value column:
value - order by:
key
Builder usage:
builder
.table
.key_column
.value_column
.order_by
.run?;
Table and column names are validated as simple SQL identifiers before being interpolated into SQL. Values are always bound as SQL parameters.
Valid identifiers are non-empty, start with an ASCII letter or _, and contain only ASCII letters, numbers, and _.
Secret Values
builder
.secret_keys
.run?;
Non-empty secret values are displayed as ********. Empty secret values are displayed as empty. The underlying value is not changed unless the user selects that setting and enters a new value.
Validation
builder
.validator
.run?;
Validation runs before a setting is updated.
Input values are trimmed before validation and saving.
Custom Actions
Custom actions are closures with no arguments. Capture app state directly when needed:
builder
.action
.run?;
Custom actions are displayed in the prompt and run when their key is selected. Action keys cannot be empty, numeric, duplicated, q, or quit.
Avoiding rusqlite Conflicts
If your application already uses a different rusqlite version, do not enable the rusqlite feature. Implement SettingsStore in your application and use the generic builder:
use ;
builder.run?;
When writing your own SQL-backed store, validate any table or column names before interpolating them into SQL. Bind setting values as parameters.
Examples
examples/custom_store.rsshows the genericSettingsStoreAPI without any database dependency.examples/sqlite_basic.rsshows the built-in SQLite adapter with the default table layout.examples/sqlite_builder.rsshows custom table names, secret keys, validation, and custom actions with SQLite.
Run examples with:
The example binaries are compile-focused and do not open the interactive menu.
Migrating from 0.1 to 0.2
0.2 moves SQLite support behind an optional feature and makes the core menu storage-agnostic.
Update dependencies:
= { = "0.2", = ["rusqlite"] }
= "0.40"
Update function paths:
// 0.1
run?;
builder.run?;
// 0.2
run?;
builder.run?;
Update custom actions:
// 0.1
builder
.action;
// 0.2
builder
.action;
Deliberately Not Included
- Creating the settings table
- Seeding default settings
- Parsing values into app-specific types
- CLI argument parsing
- Encryption or secure secret storage
- App-specific maintenance logic