...
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user