This commit is contained in:
2025-07-21 06:18:46 +02:00
parent 62932976dd
commit ddf5fcbbcc
268 changed files with 1614 additions and 2271 deletions

View File

@@ -1,271 +1,218 @@
# ParamsParser Module Documentation
# ParamsParser Module: Flexible Parameter Handling in V
The ParamsParser module provides a powerful way to parse and handle parameter strings in V. It's particularly useful for parsing command-line style arguments and key-value pairs from text.
The `ParamsParser` module in V provides a robust and intuitive way to parse and manage parameters from various string inputs, such as command-line arguments, configuration strings, or key-value data. It simplifies the extraction and type conversion of values, making it ideal for applications requiring flexible and dynamic parameter processing.
## Basic Usage
## Key Features
* **Flexible Parsing:** Supports key-value pairs, quoted values, and positional arguments.
* **Automatic Type Conversion:** Easily retrieve values as strings, integers, floats, booleans, and various list types.
* **Error Handling:** Integrates with V's error handling for reliable operations.
* **Case-Insensitive Keys:** Provides convenience by treating keys as case-insensitive.
* **Merging Capabilities:** Combine multiple parameter sets effortlessly.
## Installation
```v
import freeflowuniverse.herolib.data.paramsparser
// Create new params from text
params := paramsparser.new("color:red size:'large' priority:1 enable:true")!
// Or create empty params and add later
mut params := paramsparser.new_params()
params.set("color", "red")
```
## Parameter Format
## Basic Usage
The parser supports several formats:
### Creating Parameters
1. Key-value pairs: `key:value`
2. Quoted values: `key:'value with spaces'`
3. Arguments without keys: `arg1 arg2`
4. Comments: `// this is a comment`
You can create a new `Params` object from a string or initialize an empty one:
Example:
```v
text := "name:'John Doe' age:30 active:true // user details"
params := paramsparser.new(text)!
// 1. Create from a parameter string
params_from_string := paramsparser.new("color:red size:'large item:apple' priority:1 enable:true")!
// 2. Create an empty Params object and add values later
mut empty_params := paramsparser.new_params()
empty_params.set("product", "laptop")
empty_params.set("price", "1200")
```
## Getting Values
### Parameter String Format
The module provides various methods to retrieve values:
The parser understands several common parameter formats:
* **Key-Value Pairs:** `key:value` (e.g., `name:John`)
* **Quoted Values:** `key:'value with spaces'` or `key:"value with spaces"` (essential for values containing spaces or special characters)
* **Positional Arguments:** `arg1 arg2` (values without an explicit key)
* **Comments:** `// this is a comment` (lines starting with `//` are ignored)
**Example:**
```v
text := "user_name:'Alice Smith' age:28 active:true // user profile data"
parsed_params := paramsparser.new(text)!
// Accessing values
println(parsed_params.get("user_name")!) // Output: Alice Smith
println(parsed_params.get_int("age")!) // Output: 28
println(parsed_params.get_default_true("active")) // Output: true
```
## Retrieving Values
The `ParamsParser` offers a variety of methods to retrieve values, including type-specific getters and options for default values.
### Common Getters
```v
// Get string value
name := params.get("name")! // returns "John Doe"
name := parsed_params.get("user_name")! // Returns "Alice Smith"
// Get with default value
color := params.get_default("color", "blue")! // returns "blue" if color not set
// Get with a default value if key is not found
city := parsed_params.get_default("city", "Unknown")! // Returns "Unknown" if 'city' is not set
// Get as integer
age := params.get_int("age")! // returns 30
// Get as boolean (true if value is "1", "true", "y", "yes")
is_active := params.get_default_true("active")
age := parsed_params.get_int("age")! // Returns 28
// Get as float
score := params.get_float("score")!
temperature := parsed_params.get_float("temp")! // Converts "25.5" to 25.5
// Get as percentage (converts "80%" to 0.8)
progress := params.get_percentage("progress")!
// Get as percentage (converts "75%" to 0.75)
completion := parsed_params.get_percentage("progress")!
```
## Type Conversion Methods
The module supports various type conversions:
### Basic Types
- `get_int()`: Convert to int32
- `get_u32()`: Convert to unsigned 32-bit integer
- `get_u64()`: Convert to unsigned 64-bit integer
- `get_u8()`: Convert to unsigned 8-bit integer
- `get_float()`: Convert to 64-bit float
- `get_percentage()`: Convert percentage string to float (e.g., "80%" → 0.8)
### Boolean Values
- `get_default_true()`: Returns true if value is empty, "1", "true", "y", or "yes"
- `get_default_false()`: Returns false if value is empty, "0", "false", "n", or "no"
### Lists
The module provides robust support for parsing and converting lists:
Boolean getters are flexible and interpret common truthy/falsy strings:
* `get_default_true(key string)`: Returns `true` if the value is empty, "1", "true", "y", or "yes". Otherwise, `false`.
* `get_default_false(key string)`: Returns `false` if the value is empty, "0", "false", "n", or "no". Otherwise, `true`.
```v
// Basic list parsing
names := params.get_list("users")! // parses ["user1", "user2", "user3"]
// With default value
tags := params.get_list_default("tags", ["default"])!
// Lists with type conversion
numbers := params.get_list_int("ids")! // converts each item to int
amounts := params.get_list_f64("prices")! // converts each item to f64
// Name-fixed lists (normalizes each item)
clean_names := params.get_list_namefix("categories")!
is_enabled := parsed_params.get_default_true("enable_feature") // "enable_feature:yes" -> true
is_debug := parsed_params.get_default_false("debug_mode") // "debug_mode:0" -> false
```
Supported list types:
- `get_list()`: String list
- `get_list_u8()`, `get_list_u16()`, `get_list_u32()`, `get_list_u64()`: Unsigned integers
- `get_list_i8()`, `get_list_i16()`, `get_list_int()`, `get_list_i64()`: Signed integers
- `get_list_f32()`, `get_list_f64()`: Floating point numbers
### List Values
Each list method has a corresponding `_default` version that accepts a default value.
The module provides comprehensive support for parsing and converting lists of various types. Lists can be defined using square brackets `[]` or comma-separated values.
Valid list formats:
```v
users: ["john", "jane", "bob"]
ids: 1,2,3,4,5
names: ['John Doe', 'Jane Smith']
// Example parameter string with lists
list_params := paramsparser.new("items:['apple', 'banana', 'orange'] ids:101,102,103 prices:[1.99, 2.50, 0.75]")!
// Get a list of strings
fruits := list_params.get_list("items")! // Returns ["apple", "banana", "orange"]
// Get a list of integers
item_ids := list_params.get_list_int("ids")! // Returns [101, 102, 103]
// Get a list of floats
product_prices := list_params.get_list_f64("prices")! // Returns [1.99, 2.50, 0.75]
// Get a list with a default value if the key is not found
categories := list_params.get_list_default("categories", ["misc"])!
// Name-fixed lists (normalizes each item, e.g., "My Category" -> "my_category")
clean_tags := list_params.get_list_namefix("tags")!
```
## Working with Arguments
**Supported List Types:**
Arguments are values without keys:
* `get_list()`: `[]string`
* `get_list_u8()`, `get_list_u16()`, `get_list_u32()`, `get_list_u64()`: Unsigned integer lists
* `get_list_i8()`, `get_list_i16()`, `get_list_int()`, `get_list_i64()`: Signed integer lists
* `get_list_f32()`, `get_list_f64()`: Floating-point lists
Each list method also has a `_default` version (e.g., `get_list_int_default`) for providing fallback values.
## Working with Positional Arguments
Arguments are values provided without a key.
```v
// Parse text with arguments
params := paramsparser.new("arg1 arg2 key:value")!
// Parse text with positional arguments
arg_params := paramsparser.new("command_name --verbose file.txt")!
// Add an argument
params.set_arg("arg3")
// Add a new argument
arg_params.set_arg("another_arg")
// Check if argument exists
if params.exists_arg("arg1") {
// do something
// Check if an argument exists
if arg_params.exists_arg("file.txt") {
println("File argument found!")
}
// Get all arguments
all_args := arg_params.get_args() // Returns ["command_name", "--verbose", "file.txt", "another_arg"]
```
## Additional Features
## Advanced Features
### Case-Insensitive Keys
Keys are treated as case-insensitive for retrieval, promoting flexibility.
1. Case insensitive keys:
```v
params.set("Color", "red")
value := params.get("color")! // works
params := paramsparser.new_params()
params.set("FileName", "document.pdf")
value := params.get("filename")! // Successfully retrieves "document.pdf"
```
2. Map conversion:
### Converting to Map
Easily convert the parsed parameters into a standard V map.
```v
// Convert params to map
map_values := params.get_map()
params := paramsparser.new("key1:value1 key2:value2")!
map_representation := params.get_map()
println(map_representation["key1"]) // Output: value1
```
3. Merging params:
### Merging Parameters
Combine two `Params` objects, with values from the merged object overriding existing keys.
```v
mut params1 := paramsparser.new("color:red")!
params2 := paramsparser.new("size:large")!
mut params1 := paramsparser.new("color:red size:small")!
params2 := paramsparser.new("size:large material:wood")!
params1.merge(params2)!
// params1 now contains: color:red, size:large, material:wood
```
4. Delete parameters:
### Deleting Parameters
Remove specific key-value pairs or positional arguments.
```v
params.delete("color") // delete key-value pair
params.delete_arg("arg1") // delete argument
params := paramsparser.new("item:book quantity:5 arg1 arg2")!
params.delete("quantity") // Removes 'quantity:5'
params.delete_arg("arg1") // Removes 'arg1'
```
## Error Handling
Most methods return results that should be handled with V's error handling:
Most `ParamsParser` methods that retrieve or convert values return `Result` types, requiring explicit error handling using V's `!` operator or `or {}` block.
```v
// Using ! operator for methods that can fail
name := params.get("name")!
// Using the '!' operator (panics on error)
required_value := params.get("mandatory_key")!
// Or with or {} block for custom error handling
name := params.get("name") or {
println("Error: ${err}")
"default_name"
// Using 'or {}' for graceful error handling
optional_value := params.get("optional_key") or {
eprintln("Warning: 'optional_key' not found or invalid: ${err}")
"default_fallback_value"
}
```
## Parameter Validation
## Parameter Validation Rules
The parser enforces certain rules:
- Keys can only contain A-Z, a-z, 0-9, underscore, dot, and forward slash
- Values can contain any characters
- Spaces in values must be enclosed in quotes
- Lists are supported with comma separation
The parser adheres to the following rules for input strings:
## Best Practices
* **Keys:** Must consist of alphanumeric characters, underscores (`_`), dots (`.`), and forward slashes (`/`).
* **Values:** Can contain any characters.
* **Spaces in Values:** Must be enclosed within single (`'`) or double (`"`) quotes.
* **Lists:** Supported with comma separation or square bracket notation.
1. Always handle potential errors with `!` or `or {}`
2. Use type-specific getters (`get_int`, `get_float`, etc.) when you know the expected type
3. Provide default values when appropriate using the `_default` methods
4. Use quotes for values containing spaces
5. Use lowercase keys for consistency (though the parser is case-insensitive)
# Params Details
```v
import freeflowuniverse.herolib.data.paramsparser
mut p:=paramsparser.new('
id:a1 name6:aaaaa
name:'need to do something 1'
)!
assert "a1"==p.get_default("id","")!
```
example text to parse
```yaml
id:a1 name6:aaaaa
name:'need to do something 1'
description:
## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
name2: test
name3: hi name10:'this is with space' name11:aaa11
#some comment
name4: 'aaa'
//somecomment
name5: 'aab'
```
results in
```go
Params{
params: [Param{
key: 'id'
value: 'a1'
}, Param{
key: 'name6'
value: 'aaaaa'
}, Param{
key: 'name'
value: 'need to do something 1'
}, Param{
key: 'description'
value: '## markdown works in it
description can be multiline
lets see what happens
- a
- something else
### subtitle
'
}, Param{
key: 'name2'
value: 'test'
}, Param{
key: 'name3'
value: 'hi'
}, Param{
key: 'name10'
value: 'this is with space'
}, Param{
key: 'name11'
value: 'aaa11'
}, Param{
key: 'name4'
value: 'aaa'
}, Param{
key: 'name5'
value: 'aab'
}]
}
```
## Best Practices for Usage
1. **Always Handle Errors:** Use `!` or `or {}` to manage potential parsing or conversion failures.
2. **Use Type-Specific Getters:** Prefer `get_int()`, `get_float()`, etc., when you know the expected data type for clarity and safety.
3. **Provide Default Values:** Utilize `_default` methods (e.g., `get_default`, `get_list_default`) to ensure your application behaves predictably when parameters are missing.
4. **Quote Values with Spaces:** Always enclose values containing spaces or special characters in quotes to ensure correct parsing.
5. **Consistent Key Naming:** While case-insensitive, using a consistent naming convention (e.g., `snake_case` or `camelCase`) for keys improves human readability and maintainability.