...
This commit is contained in:
13
README.md
13
README.md
@@ -7,17 +7,6 @@ Herolib is an opinionated library primarily used by ThreeFold to automate cloud
|
|||||||
|
|
||||||
> [Complete Documentation](https://freeflowuniverse.github.io/herolib/)
|
> [Complete Documentation](https://freeflowuniverse.github.io/herolib/)
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
- [Installation](#installation)
|
|
||||||
- [For Users](#for-users)
|
|
||||||
- [For Developers](#for-developers)
|
|
||||||
- [Features](#features)
|
|
||||||
- [Testing](#testing)
|
|
||||||
- [Contributing](#contributing)
|
|
||||||
- [Troubleshooting](#troubleshooting)
|
|
||||||
- [Additional Resources](#additional-resources)
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### For Users
|
### For Users
|
||||||
@@ -27,6 +16,8 @@ The Hero tool can be installed with a single command:
|
|||||||
```bash
|
```bash
|
||||||
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /tmp/install_hero.sh
|
curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /tmp/install_hero.sh
|
||||||
bash /tmp/install_hero.sh
|
bash /tmp/install_hero.sh
|
||||||
|
#do not forget to do the following this makes sure vtest and vrun exists
|
||||||
|
bash install_herolib.vsh
|
||||||
```
|
```
|
||||||
|
|
||||||
Hero will be installed in:
|
Hero will be installed in:
|
||||||
|
|||||||
141
aiprompts/herolib_advanced/advanced_paths.md
Normal file
141
aiprompts/herolib_advanced/advanced_paths.md
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
# Pathlib Module: Advanced Listing and Filtering
|
||||||
|
|
||||||
|
The `pathlib` module provides powerful capabilities for listing and filtering files and directories, especially through its `list` method. This document explains how to leverage advanced features like regular expressions and various filtering options.
|
||||||
|
|
||||||
|
## Advanced File Listing with `path.list()`
|
||||||
|
|
||||||
|
The `path.list()` method allows you to retrieve a `PathList` object containing `Path` objects that match specified criteria.
|
||||||
|
|
||||||
|
### `ListArgs` Parameters
|
||||||
|
|
||||||
|
The `list` method accepts a `ListArgs` struct to control its behavior:
|
||||||
|
|
||||||
|
```v
|
||||||
|
pub struct ListArgs {
|
||||||
|
pub mut:
|
||||||
|
regex []string // A slice of regular expressions to filter files.
|
||||||
|
recursive bool = true // Whether to list files recursively (default true).
|
||||||
|
ignoredefault bool = true // Whether to ignore files starting with . and _ (default true).
|
||||||
|
include_links bool // Whether to include symbolic links in the list.
|
||||||
|
dirs_only bool // Whether to include only directories in the list.
|
||||||
|
files_only bool // Whether to include only files in the list.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage Examples
|
||||||
|
|
||||||
|
Here are examples demonstrating how to use these advanced filtering options:
|
||||||
|
|
||||||
|
#### 1. Listing Files by Regex Pattern
|
||||||
|
|
||||||
|
You can use regular expressions to filter files based on their names or extensions. The `regex` parameter accepts a slice of strings, where each string is a regex pattern.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
|
||||||
|
// Get a directory path
|
||||||
|
mut dir := pathlib.get('/some/directory')!
|
||||||
|
|
||||||
|
// List only Vlang files (ending with .v)
|
||||||
|
mut vlang_files := dir.list(
|
||||||
|
regex: [r'.*\.v$']
|
||||||
|
)!
|
||||||
|
|
||||||
|
// List only image files (png, jpg, svg, jpeg)
|
||||||
|
mut image_files := dir.list(
|
||||||
|
regex: [r'.*\.png$', r'.*\.jpg$', r'.*\.svg$', r'.*\.jpeg$']
|
||||||
|
)!
|
||||||
|
|
||||||
|
// List files containing "test" in their name (case-insensitive)
|
||||||
|
mut test_files := dir.list(
|
||||||
|
regex: [r'(?i).*test.*'] // (?i) makes the regex case-insensitive
|
||||||
|
)!
|
||||||
|
|
||||||
|
for path_obj in vlang_files.paths {
|
||||||
|
println(path_obj.path)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Controlling Recursion
|
||||||
|
|
||||||
|
By default, `list()` is recursive. You can disable recursion to list only items in the current directory.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
|
||||||
|
mut dir := pathlib.get('/some/directory')!
|
||||||
|
|
||||||
|
// List only top-level files and directories (non-recursive)
|
||||||
|
mut top_level_items := dir.list(
|
||||||
|
recursive: false
|
||||||
|
)!
|
||||||
|
|
||||||
|
for path_obj in top_level_items.paths {
|
||||||
|
println(path_obj.path)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Including or Excluding Hidden Files
|
||||||
|
|
||||||
|
The `ignoredefault` parameter controls whether files and directories starting with `.` or `_` are ignored.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
|
||||||
|
mut dir := pathlib.get('/some/directory')!
|
||||||
|
|
||||||
|
// List all files and directories, including hidden ones
|
||||||
|
mut all_items := dir.list(
|
||||||
|
ignoredefault: false
|
||||||
|
)!
|
||||||
|
|
||||||
|
for path_obj in all_items.paths {
|
||||||
|
println(path_obj.path)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Including Symbolic Links
|
||||||
|
|
||||||
|
By default, symbolic links are ignored when walking the directory structure. Set `include_links` to `true` to include them.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
|
||||||
|
mut dir := pathlib.get('/some/directory')!
|
||||||
|
|
||||||
|
// List files and directories, including symbolic links
|
||||||
|
mut items_with_links := dir.list(
|
||||||
|
include_links: true
|
||||||
|
)!
|
||||||
|
|
||||||
|
for path_obj in items_with_links.paths {
|
||||||
|
println(path_obj.path)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Listing Only Directories or Only Files
|
||||||
|
|
||||||
|
Use `dirs_only` or `files_only` to restrict the results to only directories or only files.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
|
||||||
|
mut dir := pathlib.get('/some/directory')!
|
||||||
|
|
||||||
|
// List only directories (recursive)
|
||||||
|
mut only_dirs := dir.list(
|
||||||
|
dirs_only: true
|
||||||
|
)!
|
||||||
|
|
||||||
|
// List only files (non-recursive)
|
||||||
|
mut only_files := dir.list(
|
||||||
|
files_only: true,
|
||||||
|
recursive: false
|
||||||
|
)!
|
||||||
|
|
||||||
|
for path_obj in only_dirs.paths {
|
||||||
|
println(path_obj.path)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
By combining these parameters, you can create highly specific and powerful file system listing operations tailored to your needs.
|
||||||
204
aiprompts/herolib_advanced/redis.md
Normal file
204
aiprompts/herolib_advanced/redis.md
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
# Redisclient Module
|
||||||
|
|
||||||
|
The `redisclient` module in Herolib provides a comprehensive client for interacting with Redis, supporting various commands, caching, queues, and RPC mechanisms.
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
- **Direct Redis Commands**: Access to a wide range of Redis commands (strings, hashes, lists, keys, etc.).
|
||||||
|
- **Caching**: Built-in caching mechanism with namespace support and expiration.
|
||||||
|
- **Queues**: Simple queue implementation using Redis lists.
|
||||||
|
- **RPC**: Remote Procedure Call (RPC) functionality over Redis queues for inter-service communication.
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
To get a Redis client instance, use `redisclient.core_get()`. By default, it connects to `127.0.0.1:6379`. You can specify a different address and port using the `RedisURL` struct.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.redisclient
|
||||||
|
|
||||||
|
// Connect to default Redis instance (127.0.0.1:6379)
|
||||||
|
mut redis := redisclient.core_get()!
|
||||||
|
|
||||||
|
// Or connect to a specific Redis instance
|
||||||
|
// mut redis_url := redisclient.RedisURL{address: 'my.redis.server', port: 6380}
|
||||||
|
// mut redis := redisclient.core_get(redis_url)!
|
||||||
|
|
||||||
|
// Example: Set and Get a key
|
||||||
|
redis.set('mykey', 'myvalue')!
|
||||||
|
value := redis.get('mykey')!
|
||||||
|
// assert value == 'myvalue'
|
||||||
|
|
||||||
|
// Example: Check if a key exists
|
||||||
|
exists := redis.exists('mykey')!
|
||||||
|
// assert exists == true
|
||||||
|
|
||||||
|
// Example: Delete a key
|
||||||
|
redis.del('mykey')!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Redis Commands
|
||||||
|
|
||||||
|
The `Redis` object provides methods for most standard Redis commands. Here are some examples:
|
||||||
|
|
||||||
|
### String Commands
|
||||||
|
|
||||||
|
- `set(key string, value string) !`: Sets the string value of a key.
|
||||||
|
- `get(key string) !string`: Gets the string value of a key.
|
||||||
|
- `set_ex(key string, value string, ex string) !`: Sets a key with an expiration time in seconds.
|
||||||
|
- `incr(key string) !int`: Increments the integer value of a key by one.
|
||||||
|
- `decr(key string) !int`: Decrements the integer value of a key by one.
|
||||||
|
- `append(key string, value string) !int`: Appends a value to a key.
|
||||||
|
- `strlen(key string) !int`: Gets the length of the value stored in a key.
|
||||||
|
|
||||||
|
```v
|
||||||
|
redis.set('counter', '10')!
|
||||||
|
redis.incr('counter')! // counter is now 11
|
||||||
|
val := redis.get('counter')! // "11"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hash Commands
|
||||||
|
|
||||||
|
- `hset(key string, skey string, value string) !`: Sets the string value of a hash field.
|
||||||
|
- `hget(key string, skey string) !string`: Gets the value of a hash field.
|
||||||
|
- `hgetall(key string) !map[string]string`: Gets all fields and values in a hash.
|
||||||
|
- `hexists(key string, skey string) !bool`: Checks if a hash field exists.
|
||||||
|
- `hdel(key string, skey string) !int`: Deletes one or more hash fields.
|
||||||
|
|
||||||
|
```v
|
||||||
|
redis.hset('user:1', 'name', 'John Doe')!
|
||||||
|
redis.hset('user:1', 'email', 'john@example.com')!
|
||||||
|
user_name := redis.hget('user:1', 'name')! // "John Doe"
|
||||||
|
user_data := redis.hgetall('user:1')! // map['name':'John Doe', 'email':'john@example.com']
|
||||||
|
```
|
||||||
|
|
||||||
|
### List Commands
|
||||||
|
|
||||||
|
- `lpush(key string, element string) !int`: Inserts all specified values at the head of the list stored at key.
|
||||||
|
- `rpush(key string, element string) !int`: Inserts all specified values at the tail of the list stored at key.
|
||||||
|
- `lpop(key string) !string`: Removes and returns the first element of the list stored at key.
|
||||||
|
- `rpop(key string) !string`: Removes and returns the last element of the list stored at key.
|
||||||
|
- `llen(key string) !int`: Gets the length of a list.
|
||||||
|
- `lrange(key string, start int, end int) ![]resp.RValue`: Gets a range of elements from a list.
|
||||||
|
|
||||||
|
```v
|
||||||
|
redis.lpush('mylist', 'item1')!
|
||||||
|
redis.rpush('mylist', 'item2')!
|
||||||
|
first_item := redis.lpop('mylist')! // "item1"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Commands
|
||||||
|
|
||||||
|
- `sadd(key string, members []string) !int`: Adds the specified members to the set stored at key.
|
||||||
|
- `smismember(key string, members []string) ![]int`: Returns if member is a member of the set stored at key.
|
||||||
|
|
||||||
|
```v
|
||||||
|
redis.sadd('myset', ['member1', 'member2'])!
|
||||||
|
is_member := redis.smismember('myset', ['member1', 'member3'])! // [1, 0]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Management
|
||||||
|
|
||||||
|
- `keys(pattern string) ![]string`: Finds all keys matching the given pattern.
|
||||||
|
- `del(key string) !int`: Deletes a key.
|
||||||
|
- `expire(key string, seconds int) !int`: Sets a key's time to live in seconds.
|
||||||
|
- `ttl(key string) !int`: Gets the time to live for a key in seconds.
|
||||||
|
- `flushall() !`: Deletes all the keys of all the existing databases.
|
||||||
|
- `flushdb() !`: Deletes all the keys of the currently selected database.
|
||||||
|
- `selectdb(database int) !`: Changes the selected database.
|
||||||
|
|
||||||
|
```v
|
||||||
|
redis.set('temp_key', 'value')!
|
||||||
|
redis.expire('temp_key', 60)! // Expires in 60 seconds
|
||||||
|
```
|
||||||
|
|
||||||
|
## Redis Cache
|
||||||
|
|
||||||
|
The `RedisCache` struct provides a convenient way to implement caching using Redis.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.redisclient
|
||||||
|
|
||||||
|
mut redis := redisclient.core_get()!
|
||||||
|
mut cache := redis.cache('my_app_cache')
|
||||||
|
|
||||||
|
// Set a value in cache with expiration (e.g., 3600 seconds)
|
||||||
|
cache.set('user:profile:123', '{ "name": "Alice" }', 3600)!
|
||||||
|
|
||||||
|
// Get a value from cache
|
||||||
|
cached_data := cache.get('user:profile:123') or {
|
||||||
|
// Cache miss, fetch from source
|
||||||
|
println('Cache miss for user:profile:123')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// println('Cached data: ${cached_data}')
|
||||||
|
|
||||||
|
// Check if a key exists in cache
|
||||||
|
exists := cache.exists('user:profile:123')
|
||||||
|
// assert exists == true
|
||||||
|
|
||||||
|
// Reset the cache for the namespace
|
||||||
|
cache.reset()!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Redis Queue
|
||||||
|
|
||||||
|
The `RedisQueue` struct provides a simple queue mechanism using Redis lists.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.redisclient
|
||||||
|
import time
|
||||||
|
|
||||||
|
mut redis := redisclient.core_get()!
|
||||||
|
mut my_queue := redis.queue_get('my_task_queue')
|
||||||
|
|
||||||
|
// Add items to the queue
|
||||||
|
my_queue.add('task1')!
|
||||||
|
my_queue.add('task2')!
|
||||||
|
|
||||||
|
// Get an item from the queue with a timeout (e.g., 1000 milliseconds)
|
||||||
|
task := my_queue.get(1000)!
|
||||||
|
// assert task == 'task1'
|
||||||
|
|
||||||
|
// Pop an item without timeout (returns error if no item)
|
||||||
|
task2 := my_queue.pop()!
|
||||||
|
// assert task2 == 'task2'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Redis RPC
|
||||||
|
|
||||||
|
The `RedisRpc` struct enables Remote Procedure Call (RPC) over Redis, allowing services to communicate by sending messages to queues and waiting for responses.
|
||||||
|
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.redisclient
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
mut redis := redisclient.core_get()!
|
||||||
|
mut rpc_client := redis.rpc_get('my_rpc_service')
|
||||||
|
|
||||||
|
// Define a function to process RPC requests (server-side)
|
||||||
|
fn my_rpc_processor(cmd string, data string) !string {
|
||||||
|
// Simulate some processing based on cmd and data
|
||||||
|
return 'Processed: cmd=${cmd}, data=${data}'
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Client Side (calling the RPC) ---
|
||||||
|
// Call the RPC service
|
||||||
|
response := rpc_client.call(
|
||||||
|
cmd: 'greet',
|
||||||
|
data: '{"name": "World"}',
|
||||||
|
wait: true,
|
||||||
|
timeout: 5000 // 5 seconds timeout
|
||||||
|
)!
|
||||||
|
// println('RPC Response: ${response}')
|
||||||
|
// assert response == 'Processed: cmd=greet, data={"name": "World"}'
|
||||||
|
|
||||||
|
// --- Server Side (processing RPC requests) ---
|
||||||
|
// In a separate goroutine or process, you would run:
|
||||||
|
// rpc_client.process(my_rpc_processor, timeout: 0)! // timeout 0 means no timeout, keeps processing
|
||||||
|
|
||||||
|
// Example of how to process a single request (for testing/demonstration)
|
||||||
|
// In a real application, this would be in a loop or a background worker
|
||||||
|
// return_queue_name := rpc_client.process(my_rpc_processor, timeout: 1000)!
|
||||||
|
// result := rpc_client.result(1000, return_queue_name)!
|
||||||
|
// println('Processed result: ${result}')
|
||||||
150
aiprompts/herolib_core/core_paths.md
Normal file
150
aiprompts/herolib_core/core_paths.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# Pathlib Usage Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The pathlib module provides a comprehensive interface for handling file system operations. Key features include:
|
||||||
|
|
||||||
|
- Robust path handling for files, directories, and symlinks
|
||||||
|
- Support for both absolute and relative paths
|
||||||
|
- Automatic home directory expansion (~)
|
||||||
|
- Recursive directory operations
|
||||||
|
- Path filtering and listing
|
||||||
|
- File and directory metadata access
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
### Importing pathlib
|
||||||
|
```v
|
||||||
|
import freeflowuniverse.herolib.core.pathlib
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating Path Objects
|
||||||
|
```v
|
||||||
|
// Create a Path object for a file
|
||||||
|
mut file_path := pathlib.get("path/to/file.txt")
|
||||||
|
|
||||||
|
// Create a Path object for a directory
|
||||||
|
mut dir_path := pathlib.get("path/to/directory")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Basic Path Operations
|
||||||
|
```v
|
||||||
|
// Get absolute path
|
||||||
|
abs_path := file_path.absolute()
|
||||||
|
|
||||||
|
// Get real path (resolves symlinks)
|
||||||
|
real_path := file_path.realpath()
|
||||||
|
|
||||||
|
// Check if path exists
|
||||||
|
if file_path.exists() {
|
||||||
|
// Path exists
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Path Properties and Methods
|
||||||
|
|
||||||
|
### Path Types
|
||||||
|
```v
|
||||||
|
// Check if path is a file
|
||||||
|
if file_path.is_file() {
|
||||||
|
// Handle as file
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if path is a directory
|
||||||
|
if dir_path.is_dir() {
|
||||||
|
// Handle as directory
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if path is a symlink
|
||||||
|
if file_path.is_link() {
|
||||||
|
// Handle as symlink
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Path Normalization
|
||||||
|
```v
|
||||||
|
// Normalize path (remove extra slashes, resolve . and ..)
|
||||||
|
normalized_path := file_path.path_normalize()
|
||||||
|
|
||||||
|
// Get path directory
|
||||||
|
dir_path := file_path.path_dir()
|
||||||
|
|
||||||
|
// Get path name without extension
|
||||||
|
name_no_ext := file_path.name_no_ext()
|
||||||
|
```
|
||||||
|
|
||||||
|
## File and Directory Operations
|
||||||
|
|
||||||
|
### File Operations
|
||||||
|
```v
|
||||||
|
// Write to file
|
||||||
|
file_path.write("Content to write")!
|
||||||
|
|
||||||
|
// Read from file
|
||||||
|
content := file_path.read()!
|
||||||
|
|
||||||
|
// Delete file
|
||||||
|
file_path.delete()!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Directory Operations
|
||||||
|
```v
|
||||||
|
// Create directory
|
||||||
|
mut dir := pathlib.get_dir(
|
||||||
|
path: "path/to/new/dir"
|
||||||
|
create: true
|
||||||
|
)!
|
||||||
|
|
||||||
|
// List directory contents
|
||||||
|
mut dir_list := dir.list()!
|
||||||
|
|
||||||
|
// Delete directory
|
||||||
|
dir.delete()!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Symlink Operations
|
||||||
|
```v
|
||||||
|
// Create symlink
|
||||||
|
file_path.link("path/to/symlink", delete_exists: true)!
|
||||||
|
|
||||||
|
// Resolve symlink
|
||||||
|
real_path := file_path.realpath()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Operations
|
||||||
|
|
||||||
|
### Path Copying
|
||||||
|
```v
|
||||||
|
// Copy file to destination
|
||||||
|
file_path.copy(dest: "path/to/destination")!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Recursive Operations
|
||||||
|
```v
|
||||||
|
// List directory recursively
|
||||||
|
mut recursive_list := dir.list(recursive: true)!
|
||||||
|
|
||||||
|
// Delete directory recursively
|
||||||
|
dir.delete()!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Path Filtering
|
||||||
|
```v
|
||||||
|
// List files matching pattern
|
||||||
|
mut filtered_list := dir.list(
|
||||||
|
regex: [r".*\.txt$"],
|
||||||
|
recursive: true
|
||||||
|
)!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
```v
|
||||||
|
if file_path.exists() {
|
||||||
|
// Safe to operate
|
||||||
|
} else {
|
||||||
|
// Handle missing file
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
@@ -15,3 +15,4 @@ the files are in ~/code/github/freeflowuniverse/herolib/examples for herolib
|
|||||||
|
|
||||||
- never use fn main() in a .vsh script
|
- never use fn main() in a .vsh script
|
||||||
- always use the top line as in example above
|
- always use the top line as in example above
|
||||||
|
- these scripts can be executed as is but can also use vrun $pathOfFile
|
||||||
|
|||||||
11
aiprompts/herolib_core/example_script_curdir.md
Normal file
11
aiprompts/herolib_core/example_script_curdir.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Getting the Current Script's Path in Herolib/V Shell
|
||||||
|
|
||||||
|
can be used in any .v or .vsh script, easy to find content close to the script itself.
|
||||||
|
|
||||||
|
```v
|
||||||
|
#!/usr/bin/env vsh
|
||||||
|
|
||||||
|
const script_path = os.dir(@FILE) + '/scripts'
|
||||||
|
echo "Current scripts directory: ${script_directory}"
|
||||||
|
|
||||||
|
```
|
||||||
@@ -18,8 +18,15 @@ when I generate vlang scripts I will always use .vsh extension and use following
|
|||||||
- in .vsh file there is no need for a main() function
|
- in .vsh file there is no need for a main() function
|
||||||
- these scripts can be used for examples or instruction scripts e.g. an installs script
|
- these scripts can be used for examples or instruction scripts e.g. an installs script
|
||||||
|
|
||||||
|
## executing vlang scripts
|
||||||
|
|
||||||
## when creating a test script
|
As AI agent I should also execute v or .vsh scripts with vrun
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vrun ~/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel.vsh
|
||||||
|
```
|
||||||
|
|
||||||
|
## executing test scripts
|
||||||
|
|
||||||
instruct user to test as follows (vtest is an alias which gets installed when herolib gets installed), can be done for a dir and for a file
|
instruct user to test as follows (vtest is an alias which gets installed when herolib gets installed), can be done for a dir and for a file
|
||||||
|
|
||||||
|
|||||||
45
aiprompts/v_advanced/compress.md
Normal file
45
aiprompts/v_advanced/compress.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
The `compress` module in V provides low-level functionalities for compressing and decompressing byte arrays.
|
||||||
|
|
||||||
|
**Functions Overview (Low-Level):**
|
||||||
|
|
||||||
|
* **`compress(data []u8, flags int) ![]u8`**: Compresses an array of bytes.
|
||||||
|
* **`decompress(data []u8, flags int) ![]u8`**: Decompresses an array of bytes.
|
||||||
|
* **`decompress_with_callback(data []u8, cb ChunkCallback, userdata voidptr, flags int) !u64`**: Decompresses byte arrays using a callback function for chunks.
|
||||||
|
|
||||||
|
**Type Definition (Low-Level):**
|
||||||
|
|
||||||
|
* **`ChunkCallback`**: A function type `fn (chunk []u8, userdata voidptr) int` used to receive decompressed chunks.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**`compress.gzip` Module (High-Level Gzip Operations):**
|
||||||
|
|
||||||
|
For high-level gzip compression and decompression, use the `compress.gzip` module. This module provides a more convenient and recommended way to handle gzip operations compared to the low-level `compress` module.
|
||||||
|
|
||||||
|
**Key Features of `compress.gzip`:**
|
||||||
|
|
||||||
|
* **`compress(data []u8, params CompressParams) ![]u8`**: Compresses data using gzip, allowing specification of `CompressParams` like `compression_level` (0-4095).
|
||||||
|
* **`decompress(data []u8, params DecompressParams) ![]u8`**: Decompresses gzip-compressed data, allowing specification of `DecompressParams` for verification.
|
||||||
|
* **`decompress_with_callback(data []u8, cb compr.ChunkCallback, userdata voidptr, params DecompressParams) !int`**: Decompresses gzip data with a callback for chunks, similar to the low-level version but for gzip streams.
|
||||||
|
* **`validate(data []u8, params DecompressParams) !GzipHeader`**: Validates a gzip header and returns its details.
|
||||||
|
|
||||||
|
**Parameter Structures:**
|
||||||
|
|
||||||
|
* **`CompressParams`**: Configures compression, primarily `compression_level` (0-4095).
|
||||||
|
* **`DecompressParams`**: Configures decompression, including `verify_header_checksum`, `verify_length`, and `verify_checksum`.
|
||||||
|
* **`GzipHeader`**: Represents the structure of a gzip header.
|
||||||
|
|
||||||
|
**Inline Code Example (Gzip Compression/Decompression):**
|
||||||
|
|
||||||
|
```v
|
||||||
|
import compress.gzip
|
||||||
|
|
||||||
|
data := 'Hello, Gzip!'
|
||||||
|
compressed := gzip.compress(data.bytes(), compression_level: 4095)!
|
||||||
|
decompressed := gzip.decompress(compressed)!
|
||||||
|
|
||||||
|
// Check if decompressed data matches original
|
||||||
|
// if data.bytes() == decompressed { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important Note:** Always prefer `compress.gzip` for general gzip compression/decompression tasks over the low-level `compress` module.
|
||||||
12
examples/biztools/bizmodel_complete.vsh
Executable file
12
examples/biztools/bizmodel_complete.vsh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.biz.bizmodel
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
heroscript := os.join_path(os.dir(@FILE), 'examples/complete.heroscript')
|
||||||
|
|
||||||
|
// Execute the script and print results
|
||||||
|
bizmodel.play(heroscript_path:heroscript)!
|
||||||
|
mut bm := bizmodel.get("threefold")!
|
||||||
|
bm.sheet.pprint(nr_columns: 25)!
|
||||||
52
examples/biztools/examples/complete.heroscript
Normal file
52
examples/biztools/examples/complete.heroscript
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Define departments
|
||||||
|
!!bizmodel.department_define bizname:'threefold' name:'engineering' descr:'Engineering Department'
|
||||||
|
!!bizmodel.department_define bizname:'threefold' name:'operations' descr:'Operations Department'
|
||||||
|
!!bizmodel.department_define bizname:'threefold' name:'sales' descr:'Sales Department'
|
||||||
|
!!bizmodel.department_define bizname:'threefold' name:'admin' descr:'Administrative Department'
|
||||||
|
|
||||||
|
// Define engineering team with 10 people growing 10%/year (max 20)
|
||||||
|
!!bizmodel.employee_define bizname:'threefold' name:'engineering_team' descr:'Engineering Team'
|
||||||
|
nrpeople:'0:10,12:11,24:12,36:13,48:14,60:15,72:16,84:17,96:18,108:19,120:20'
|
||||||
|
cost:'5000USD'
|
||||||
|
indexation:'10%'
|
||||||
|
department:'engineering'
|
||||||
|
|
||||||
|
// Define operations team with 2 people and 4% of revenue
|
||||||
|
!!bizmodel.employee_define bizname:'threefold' name:'operations_team' descr:'Operations Team'
|
||||||
|
nrpeople:'2'
|
||||||
|
cost:'2000USD'
|
||||||
|
cost_percent_revenue:'4%'
|
||||||
|
department:'operations'
|
||||||
|
|
||||||
|
// Define sales team (placeholder)
|
||||||
|
!!bizmodel.employee_define bizname:'threefold' name:'sales_team' descr:'Sales Department'
|
||||||
|
nrpeople:'3'
|
||||||
|
cost:'4000USD'
|
||||||
|
department:'sales'
|
||||||
|
|
||||||
|
// Define admin team (placeholder)
|
||||||
|
!!bizmodel.employee_define bizname:'threefold' name:'admin_team' descr:'Administrative Team'
|
||||||
|
nrpeople:'2'
|
||||||
|
cost:'3000USD'
|
||||||
|
department:'admin'
|
||||||
|
|
||||||
|
// Define revenue stream
|
||||||
|
!!bizmodel.revenue_define bizname:'threefold' name:'cloud_services'
|
||||||
|
descr:'Cloud Services Revenue'
|
||||||
|
revenue:'10:10000,36:1000000'
|
||||||
|
extrapolate:1
|
||||||
|
// 5% annual growth after 3 years (36 months)
|
||||||
|
// Manually define growth for 5 years: 1.05^1, 1.05^2, etc.
|
||||||
|
// This is a simplified representation
|
||||||
|
// Actual implementation would need precise month:amount pairs
|
||||||
|
|
||||||
|
// Define travel cost at 3% of revenue
|
||||||
|
!!bizmodel.cost_define bizname:'threefold' name:'travel_cost'
|
||||||
|
descr:'Travel Expenses'
|
||||||
|
cost_percent_revenue:'3%'
|
||||||
|
|
||||||
|
// Define initial funding
|
||||||
|
!!bizmodel.funding_define bizname:'threefold' name:'initial_funding'
|
||||||
|
descr:'Initial Funding'
|
||||||
|
investment:'0:5000000'
|
||||||
|
type:'capital'
|
||||||
29
examples/compress_gzip_example.vsh
Normal file
29
examples/compress_gzip_example.vsh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env -S v -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib...
|
||||||
|
import compress.gzip
|
||||||
|
|
||||||
|
// Define some sample data to compress
|
||||||
|
data := 'Hello, VLang Gzip Compression Example! This is some sample text to be compressed and then decompressed.'
|
||||||
|
|
||||||
|
println('Original Data: "${data}"')
|
||||||
|
println('Original Data Length: ${data.len}')
|
||||||
|
|
||||||
|
// Compress the data using gzip
|
||||||
|
// Using a compression_level of 4095 for best compression
|
||||||
|
compressed_data := gzip.compress(data.bytes(), compression_level: 4095)!
|
||||||
|
|
||||||
|
println('Compressed Data Length: ${compressed_data.len}')
|
||||||
|
|
||||||
|
// Decompress the data
|
||||||
|
decompressed_data := gzip.decompress(compressed_data)!
|
||||||
|
|
||||||
|
println('Decompressed Data: "${decompressed_data.string()}"')
|
||||||
|
println('Decompressed Data Length: ${decompressed_data.len}')
|
||||||
|
|
||||||
|
// Verify if the decompressed data matches the original data
|
||||||
|
if data.bytes() == decompressed_data {
|
||||||
|
println('Compression and decompression successful! Data matches.')
|
||||||
|
} else {
|
||||||
|
println('Error: Decompressed data does not match original data.')
|
||||||
|
}
|
||||||
@@ -68,7 +68,10 @@ addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -show-c-outp
|
|||||||
eprintln('Failed to add vtest alias: ${err}')
|
eprintln('Failed to add vtest alias: ${err}')
|
||||||
}
|
}
|
||||||
|
|
||||||
//alias vtest='v -gc none -stats -enable-globals -show-c-output -keepc -n -w -cg -o /tmp/tester.c -g -cc tcc test'
|
// Add vrun alias
|
||||||
|
addtoscript('alias vrun=', 'alias vrun=\'v -stats -enable-globals -show-c-output -n -w -cg -gc none -cc tcc run\' ') or {
|
||||||
|
eprintln('Failed to add vrun alias: ${err}')
|
||||||
|
}
|
||||||
|
|
||||||
addtoscript('HOME/hero/bin', 'export PATH="\$PATH:\$HOME/hero/bin"') or {
|
addtoscript('HOME/hero/bin', 'export PATH="\$PATH:\$HOME/hero/bin"') or {
|
||||||
eprintln('Failed to add path to hero, ${err}')
|
eprintln('Failed to add path to hero, ${err}')
|
||||||
|
|||||||
Reference in New Issue
Block a user