Skip to content

Commit b8d19c9

Browse files
bordeuxclaude
andcommitted
feat: add data serialization functions and enhance read_lines
## New Features ### Data Serialization Functions - Add `to_json(object, pretty)` - Convert objects to JSON strings - Optional pretty-printing with indentation - Supports all data types (objects, arrays, primitives) - Add `to_yaml(object)` - Convert objects to YAML strings - Clean, human-readable output - Supports nested structures and arrays - Add `to_toml(object)` - Convert objects to TOML strings - Supports tables, nested tables, and array of tables - Ideal for configuration files ### Enhanced read_lines Function - Extend `read_lines(path, max_lines)` with flexible line selection: - Positive number: Read first N lines (existing behavior) - Negative number: Read last N lines (new) - Zero: Read entire file (new) - Useful for log file analysis and tail-like operations ## Implementation Details - Create src/functions/serialization.rs with all 3 functions - Modify read_lines to support negative/zero max_lines values - Register functions in mod.rs - Add 29 comprehensive serialization tests - Add 3 new read_lines tests for edge cases - Total: 505 passing tests ## Documentation - Add "Data Serialization Functions" section to README.md - Complete examples for each function - Practical use cases (Kubernetes configs, Cargo.toml, format conversion) - Update read_lines documentation with all modes - Update TODO.md to mark serialization as complete - Add to features list and table of contents 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 60e0953 commit b8d19c9

7 files changed

Lines changed: 1024 additions & 45 deletions

File tree

README.md

Lines changed: 213 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ A fast and simple command-line template rendering tool using [MiniJinja](https:/
2626
- [Filesystem Functions](#filesystem-functions)
2727
- [Path Manipulation Functions](#path-manipulation-functions)
2828
- [Data Parsing Functions](#data-parsing-functions)
29+
- [Data Serialization Functions](#data-serialization-functions)
2930
- [Validation Functions](#validation-functions)
3031
- [Debugging & Development Functions](#debugging--development-functions)
3132
- [Advanced Examples](#advanced-examples)
@@ -74,6 +75,7 @@ tmpltool greeting.tmpl
7475
- **Encoding & Security**: Base64, hex, bcrypt, HMAC, HTML/XML/shell escaping, secure random strings
7576
- **Filesystem**: Read files, check existence, list directories, glob patterns, file info, path manipulation
7677
- **Data Parsing**: Parse and read JSON, YAML, TOML files
78+
- **Data Serialization**: Convert objects to JSON, YAML, TOML strings with pretty-printing options
7779
- **Validation**: Validate emails, URLs, IPs, UUIDs, regex matching
7880
- **System & Network**: Get hostname, username, directories, IP addresses, DNS resolution, port availability
7981
- **Debugging & Development**: Debug output, type checking, assertions, warnings, error handling
@@ -1553,11 +1555,14 @@ Check if a path is a symbolic link.
15531555
15541556
#### `read_lines(path, max_lines)`
15551557
1556-
Read the first N lines from a file.
1558+
Read lines from a file with flexible line selection.
15571559
15581560
**Arguments:**
15591561
- `path` (required) - Path to file
1560-
- `max_lines` (optional) - Maximum number of lines to read (default: 10, max: 10000)
1562+
- `max_lines` (optional) - Number of lines to read (default: 10, max abs value: 10000)
1563+
- **Positive number**: Read first N lines
1564+
- **Negative number**: Read last N lines
1565+
- **Zero**: Read entire file
15611566
15621567
**Returns:** Array of strings (lines without newline characters)
15631568
@@ -1566,12 +1571,23 @@ Read the first N lines from a file.
15661571
**Examples:**
15671572
```jinja
15681573
{# Read first 5 lines #}
1569-
{% set lines = read_lines(path="log.txt", max_lines=5) %}
1574+
{% set first_lines = read_lines(path="log.txt", max_lines=5) %}
15701575
Recent log entries:
1571-
{% for line in lines %}
1576+
{% for line in first_lines %}
15721577
{{ loop.index }}: {{ line }}
15731578
{% endfor %}
15741579
1580+
{# Read last 5 lines #}
1581+
{% set last_lines = read_lines(path="log.txt", max_lines=-5) %}
1582+
Latest log entries:
1583+
{% for line in last_lines %}
1584+
{{ line }}
1585+
{% endfor %}
1586+
1587+
{# Read entire file #}
1588+
{% set all_lines = read_lines(path="config.txt", max_lines=0) %}
1589+
Total lines: {{ all_lines | length }}
1590+
15751591
{# Preview file content #}
15761592
{% if is_file(path="README.md") %}
15771593
README preview (first 3 lines):
@@ -1580,15 +1596,13 @@ Recent log entries:
15801596
{% endfor %}
15811597
{% endif %}
15821598
1583-
{# Count non-empty lines #}
1584-
{% set lines = read_lines(path="data.csv", max_lines=100) %}
1585-
{% set count = 0 %}
1586-
{% for line in lines %}
1587-
{% if line | trim %}
1588-
{% set count = count + 1 %}
1599+
{# Process log file tail #}
1600+
{% set log_tail = read_lines(path="app.log", max_lines=-10) %}
1601+
{% for line in log_tail %}
1602+
{% if "ERROR" in line %}
1603+
⚠️ {{ line }}
15891604
{% endif %}
15901605
{% endfor %}
1591-
Non-empty lines: {{ count }}
15921606
```
15931607
15941608
**Practical Example - Project Structure:**
@@ -1817,6 +1831,194 @@ Rust Version: {{ toml_config.package.edition }}
18171831
Dependencies: {{ toml_config.dependencies | length }}
18181832
```
18191833
1834+
### Data Serialization Functions
1835+
1836+
Convert objects and data structures to formatted strings (JSON, YAML, TOML). Useful for generating configuration files, API payloads, or converting between formats.
1837+
1838+
#### `to_json(object, pretty)`
1839+
1840+
Convert an object to a JSON string.
1841+
1842+
**Arguments:**
1843+
- `object` (required) - Object/value to convert to JSON
1844+
- `pretty` (optional) - Enable pretty-printing with indentation (default: false)
1845+
1846+
**Returns:** JSON string
1847+
1848+
**Examples:**
1849+
```jinja
1850+
{# Simple JSON serialization #}
1851+
{% set config = {"host": "localhost", "port": 8080, "debug": true} %}
1852+
{{ to_json(object=config) }}
1853+
{# Output: {"host":"localhost","port":8080,"debug":true} #}
1854+
1855+
{# Pretty-printed JSON #}
1856+
{{ to_json(object=config, pretty=true) }}
1857+
{# Output:
1858+
{
1859+
"host": "localhost",
1860+
"port": 8080,
1861+
"debug": true
1862+
}
1863+
#}
1864+
1865+
{# Convert array to JSON #}
1866+
{% set items = [1, 2, 3, 4, 5] %}
1867+
{{ to_json(object=items) }}
1868+
{# Output: [1,2,3,4,5] #}
1869+
1870+
{# Generate API payload #}
1871+
{% set api_request = {
1872+
"method": "POST",
1873+
"endpoint": "/api/users",
1874+
"data": {
1875+
"username": get_env(name="USERNAME"),
1876+
"email": get_env(name="EMAIL")
1877+
}
1878+
} %}
1879+
{{ to_json(object=api_request, pretty=true) }}
1880+
```
1881+
1882+
#### `to_yaml(object)`
1883+
1884+
Convert an object to a YAML string.
1885+
1886+
**Arguments:**
1887+
- `object` (required) - Object/value to convert to YAML
1888+
1889+
**Returns:** YAML string
1890+
1891+
**Examples:**
1892+
```jinja
1893+
{# Simple YAML serialization #}
1894+
{% set config = {"host": "localhost", "port": 8080, "debug": true} %}
1895+
{{ to_yaml(object=config) }}
1896+
{# Output:
1897+
host: localhost
1898+
port: 8080
1899+
debug: true
1900+
#}
1901+
1902+
{# Convert array to YAML #}
1903+
{% set items = ["apple", "banana", "cherry"] %}
1904+
{{ to_yaml(object=items) }}
1905+
{# Output:
1906+
- apple
1907+
- banana
1908+
- cherry
1909+
#}
1910+
1911+
{# Generate Kubernetes config #}
1912+
{% set k8s_config = {
1913+
"apiVersion": "v1",
1914+
"kind": "ConfigMap",
1915+
"metadata": {
1916+
"name": get_env(name="APP_NAME", default="myapp"),
1917+
"namespace": get_env(name="NAMESPACE", default="default")
1918+
},
1919+
"data": {
1920+
"database.url": get_env(name="DATABASE_URL"),
1921+
"cache.enabled": "true"
1922+
}
1923+
} %}
1924+
{{ to_yaml(object=k8s_config) }}
1925+
```
1926+
1927+
#### `to_toml(object)`
1928+
1929+
Convert an object to a TOML string.
1930+
1931+
**Arguments:**
1932+
- `object` (required) - Object/value to convert to TOML
1933+
1934+
**Returns:** TOML string
1935+
1936+
**Note:** TOML has specific requirements:
1937+
- Root level must be a table (object/map)
1938+
- Arrays must contain elements of the same type
1939+
1940+
**Examples:**
1941+
```jinja
1942+
{# Simple TOML serialization #}
1943+
{% set config = {"title": "My App", "version": "1.0.0"} %}
1944+
{{ to_toml(object=config) }}
1945+
{# Output:
1946+
title = "My App"
1947+
version = "1.0.0"
1948+
#}
1949+
1950+
{# Generate Cargo.toml dependencies #}
1951+
{% set cargo_config = {
1952+
"package": {
1953+
"name": get_env(name="PACKAGE_NAME", default="myapp"),
1954+
"version": "1.0.0",
1955+
"edition": "2021"
1956+
},
1957+
"dependencies": {
1958+
"serde": "1.0",
1959+
"tokio": {"version": "1.0", "features": ["full"]}
1960+
}
1961+
} %}
1962+
{{ to_toml(object=cargo_config) }}
1963+
{# Output:
1964+
[package]
1965+
name = "myapp"
1966+
version = "1.0.0"
1967+
edition = "2021"
1968+
1969+
[dependencies]
1970+
serde = "1.0"
1971+
1972+
[dependencies.tokio]
1973+
version = "1.0"
1974+
features = ["full"]
1975+
#}
1976+
1977+
{# Array of tables #}
1978+
{% set database_config = {
1979+
"database": [
1980+
{"name": "primary", "host": "db1.example.com", "port": 5432},
1981+
{"name": "replica", "host": "db2.example.com", "port": 5432}
1982+
]
1983+
} %}
1984+
{{ to_toml(object=database_config) }}
1985+
{# Output:
1986+
[[database]]
1987+
name = "primary"
1988+
host = "db1.example.com"
1989+
port = 5432
1990+
1991+
[[database]]
1992+
name = "replica"
1993+
host = "db2.example.com"
1994+
port = 5432
1995+
#}
1996+
```
1997+
1998+
**Practical Example - Format Conversion:**
1999+
```jinja
2000+
{# Read JSON, convert to YAML #}
2001+
{% set json_config = read_json_file(path="config.json") %}
2002+
2003+
# Generated YAML from JSON config
2004+
{{ to_yaml(object=json_config) }}
2005+
2006+
{# Read environment variables and generate TOML #}
2007+
{% set env_config = {
2008+
"server": {
2009+
"host": get_env(name="SERVER_HOST", default="0.0.0.0"),
2010+
"port": get_env(name="SERVER_PORT", default="8080") | int,
2011+
"workers": get_env(name="WORKERS", default="4") | int
2012+
},
2013+
"database": {
2014+
"url": get_env(name="DATABASE_URL", default="postgres://localhost/mydb"),
2015+
"max_connections": get_env(name="DB_MAX_CONN", default="10") | int
2016+
}
2017+
} %}
2018+
2019+
{{ to_toml(object=env_config) }}
2020+
```
2021+
18202022
### System & Network Functions
18212023
18222024
Access system information and perform network operations.

TODO.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ This document contains ideas for new functions and features to make tmpltool mor
5555
- [x] `read_yaml_file(path)` - Read and parse YAML file
5656
- [x] `read_toml_file(path)` - Read and parse TOML file
5757

58+
### ✅ Data Serialization
59+
- [x] `to_json(object, pretty)` - Convert object to JSON string
60+
- [x] `to_yaml(object)` - Convert object to YAML string
61+
- [x] `to_toml(object)` - Convert object to TOML string
62+
5863
### ✅ Validation
5964
- [x] `is_email(string)` - Validate email format
6065
- [x] `is_url(string)` - Validate URL format
@@ -167,9 +172,9 @@ This document contains ideas for new functions and features to make tmpltool mor
167172
*Advanced data manipulation*
168173

169174
**Serialization:**
170-
- [ ] `to_json(object, pretty)` - Convert object to JSON string
171-
- [ ] `to_yaml(object)` - Convert object to YAML string
172-
- [ ] `to_toml(object)` - Convert object to TOML string
175+
- [x] `to_json(object, pretty)` - Convert object to JSON string
176+
- [x] `to_yaml(object)` - Convert object to YAML string
177+
- [x] `to_toml(object)` - Convert object to TOML string
173178

174179
**Object Functions:**
175180
- [ ] `object_merge(obj1, obj2)` - Deep merge two objects

0 commit comments

Comments
 (0)