Readme
π₯€ colap β A Refreshingly Simple Configuration Language Parser & Code Generator
Tired of fighting with your config files? So were we.
cola is a lightweight, human-friendly configuration language designed to avoid YAMLβs whitespace traps, JSONβs curly-brace fatigue, and TOMLβs dotted-key spaghetti. Itβs backed by colap , a Rust parser and code generator that makes working with configurations effortless.
Cola is:
β
Readable β Clean nesting with minimal punctuation.
β
Writable β No indentation anxiety. No trailing comma drama.
β
Composable β Works standalone or embedded in Markdown as fenced cola ... blocks.
π Why cola?
YAML: Tabs vs Spaces
Miss one indent, and your app silently loads nonsense.
JSON: Curly Braces Forever
Nested configs turn into a forest of { } and [ ] .
TOML: Dotted-Key Spaghetti
Deep nesting forces verbose dotted keys or confusing table headers.
cola: Refreshingly Simple
π Not whitespace sensitive β Tabs? Spaces? Mix them. Cola doesnβt care.
β
Minimal punctuation β Just : for nesting and ; to end blocks.
π·οΈ Infix plural syntax β Explicitly name singular and plural forms for code generators.
π Markdown-native β Embed configs directly in documentation.
π Example Configuration
Here's a real-world configuration defining multiple LLM providers:
llm plural llms:
openai:
api:
type : " REST" ,
key: " some_api_key" ,
base_url: " some_base_url"
;
model plural models:
gpt- 4. 1 :
name: " gpt-4.1" ,
max_input_tokens: 1048576 ,
output_price: 8. 0 ,
supports_vision: true
;
gpt- 4o:
name: " gpt-4o" ,
max_input_tokens: 1048576 ,
output_price: 8. 0 ,
supports_vision: true
;
;
;
;
π cola vs YAML / JSON / TOML
Feature
YAML
JSON
TOML
cola
Whitespace sensitivity
π¬ Yes
π No
π No
β
No
Curly brace clutter
π Minimal
π© Lots
π Minimal
β
Minimal
Trailing commas allowed
β No
β No
β
Yes
β
Yes
Multi-line strings
π€ Hard
π Escapes
β
Easy
β
Easy
Collections (arrays/maps)
π Indents
π© [ ] , { }
π Mixed
β
Infix plural
Markdown embedding
β Awkward
β Awkward
β Awkward
β
First-class
π― Design Philosophy
πΉ Why Semicolons?
Cola uses ; as a block terminator:
Prevents ambiguity at the end of nested blocks.
Avoids silent parsing errors from missing indentation (YAML) or commas (JSON).
Familiar and clear for both humans and parsers.
πΉ Why Infix plural ?
model plural models:
gpt- 4 :
name: " gpt-4"
;
gpt- 4o:
name: " gpt-4o"
;
;
Makes singular and plural forms explicit in configuration.
Eliminates brittle βadd an s β heuristics in code generation.
Supports irregular plurals (e.g. person plural people ).
Improves clarity: developers instantly know single vs multiple semantics.
π§ Features
Parser
Parses standalone . cola files and Markdown files with embedded cola blocks
Produces structured configuration models
Code Generator
Generates idiomatic Rust structs and collections (HashMap ) from cola models
Handles plural entities clearly
Renames Rust keywords (e.g., type to type_ )
Provides constructors and accessor methods for easy integration
π¦ Installation
Add colap to your Rust project:
[ dependencies ]
colap = " 0.1"
π Codebase Structure
The colap codebase is organized into the following modules:
parser : Handles parsing of Cola syntax using rustemo
cola.rs : Generated parser code
cola_actions.rs : Parser actions
model : Contains the configuration model definitions
config_model.rs : Core configuration model and node types
model_builder.rs : Builds config model from parsed AST
source_location.rs : Source location tracking
generator : Code generation for Rust structs
generator_impl.rs : Main code generator implementation
templates/ : Handlebars templates for code generation
grammar : Contains the rustemo grammar definition
cola. rustemo : Grammar rules for the Cola language
π© Usage
Command Line Interface
USAGE:
colap [ OPTIONS] < input>
ARGS:
< input> Input .cola file or markdown containing Cola code blocks
OPTIONS:
-h, -- help Print help information
-m, -- mode < MODE> Generation mode: ' crate' or ' module' (default: crate )
-n, -- crate-name < NAME> Name of the generated library crate (default: input-file-stem-config )
-o, -- output < DIR> Base output directory (default: generated )
-V, -- version Print version information
Examples
Basic Crate Generation (Default)
Generate a complete Rust crate from a cola file:
colap path/to/myconfig.cola
This will:
Parse myconfig. cola
Generate code in the directory generated/myconfig-config/
Create a complete library crate with:
Cargo.toml with dependencies
src/lib.rs with generated structs
tests/integration.rs with integration tests
README.md with usage documentation
Module Generation
Generate a single Rust module file for embedding in your project:
colap path/to/myconfig.cola -- mode module - o src - n config_parser
This will:
Parse myconfig. cola
Generate a single file src/config_parser.rs
Include inline unit tests within the module
Ready to be imported with mod config_parser ; in your project
Custom crate name and output directory
colap path/to/myconfig.cola -- crate-name my-custom-config -- output custom/output/dir
This will:
Parse myconfig. cola
Generate code in the directory custom/output/dir/my-custom-config/
Create a library crate with generated structs in custom/output/dir/my-custom-config/lib.rs
Code Generation Details
The code generator produces:
Rust structs for each entity type in the configuration
Collection structs (using HashMap ) for plural entities
Accessor methods to retrieve fields and collections
Constructors for each entity type
Integration tests for validating parsing functionality
Generated Code Structure
For a configuration file with entities like Root , Llm , and Model , the generator produces:
// Root entity struct
pub struct Root {
llm : Llm,
// other fields...
}
// Singular entity
pub struct Llm {
provider : String,
models : Models, // plural entity reference
// other fields...
}
// Plural entity (collection)
pub struct Models {
entries : HashMap< String , Model> ,
}
// Entity in a collection
pub struct Model {
name : String,
context_window : i64 ,
// other fields...
}
Type Handling
The generator maps Cola types to Rust types as follows:
Cola Type
Rust Type
String
String
Integer
i64
Float
f64
Boolean
bool
Entity
Custom struct
Optional Entity
Option < CustomStruct>
Default Crate Name
If the --crate-name option is not provided, the crate name is derived from the input file:
Take the file stem (filename without extension)
Replace underscores with hyphens
Convert to lowercase
Append - config suffix
For example:
my_config. cola β my-config-config
API_Model.md β api-model-config
Using the Generated Code
Loading and Parsing a Configuration File
The generated code includes integration tests that demonstrate how to parse configuration files:
use colap:: cola:: ColaParser;
use colap:: model_builder:: ModelBuilder;
use my_config:: Root; // Generated crate name
// Load and parse a configuration file
fn parse_config_file ( path : & str ) -> Root {
// Read the file content
let content = std:: fs:: read_to_string( path) . expect ( " Failed to read config file" ) ;
// Create a parser and parse the content
let parser = ColaParser:: new( ) ;
let result = parser. parse ( & content) . expect ( " Failed to parse configuration" ) ;
// Build the configuration model
let model = ModelBuilder:: build_config_model( & result) . expect ( " Failed to build config model" ) ;
// Create the root entity from the model
Root:: from_model( & model)
}
// Usage example
let config = parse_config_file ( " path/to/config.md" ) ;
Accessing Configuration Values
The generated code provides accessor methods for retrieving values:
// Get the LLM configuration
let llm = config. llm ( ) ;
// Access a singular entity's properties
let provider = llm. provider ( ) ; // Returns a &String
// Access a collection (plural entity)
let models = llm. models ( ) ;
// Get a specific model from the collection
if let Some ( gpt4) = models. get ( " gpt-4.1" ) {
let context_window = gpt4. context_window ( ) ; // Returns an i64
println! ( " GPT-4.1 context window: {} " , context_window) ;
}
// Iterate through all models
for ( name, model) in models. iter ( ) {
println! ( " Model: {} , Context: {} " , name, model. context_window ( ) ) ;
}
Optional Fields
Optional fields are represented as Option < T> types:
// Optional field access with safe pattern matching
if let Some ( api) = llm. api ( ) {
if let Some ( key) = api. key ( ) {
println! ( " API Key: {} " , key) ;
}
}
// Using map() for clean optional chaining
let api_type = llm. api ( ) . and_then ( | api | api. type_ ( ) ) . unwrap_or ( " No API type specified" ) ;
π Embedded Markdown Support
Colap parses configurations directly from Markdown. Any fenced block marked ```cola is automatically parsed, supporting documentation-driven development.
π License
This project is licensed under the Apache License 2.0 .
Copyright 2025 Aivolution GmbH