From 8282bdf6d5e4a3092f5d3e5df3d1db252f008b2e Mon Sep 17 00:00:00 2001 From: despiegk Date: Mon, 21 Jul 2025 11:16:51 +0200 Subject: [PATCH] ... --- README.md | 13 +- aiprompts/herolib_advanced/advanced_paths.md | 141 ++++++++++++ aiprompts/herolib_advanced/redis.md | 204 ++++++++++++++++++ aiprompts/herolib_core/core_paths.md | 150 +++++++++++++ aiprompts/herolib_core/core_vshell.md | 1 + .../herolib_core/example_script_curdir.md | 11 + aiprompts/herolib_start_here.md | 9 +- aiprompts/v_advanced/compress.md | 45 ++++ examples/biztools/bizmodel_complete.vsh | 12 ++ .../biztools/examples/complete.heroscript | 52 +++++ examples/compress_gzip_example.vsh | 29 +++ install_herolib.vsh | 5 +- 12 files changed, 659 insertions(+), 13 deletions(-) create mode 100644 aiprompts/herolib_advanced/advanced_paths.md create mode 100644 aiprompts/herolib_advanced/redis.md create mode 100644 aiprompts/herolib_core/core_paths.md create mode 100644 aiprompts/herolib_core/example_script_curdir.md create mode 100644 aiprompts/v_advanced/compress.md create mode 100755 examples/biztools/bizmodel_complete.vsh create mode 100644 examples/biztools/examples/complete.heroscript create mode 100644 examples/compress_gzip_example.vsh diff --git a/README.md b/README.md index b1788721..dabc28aa 100644 --- a/README.md +++ b/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/) -## 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 ### For Users @@ -27,6 +16,8 @@ The Hero tool can be installed with a single command: ```bash curl https://raw.githubusercontent.com/freeflowuniverse/herolib/refs/heads/development/install_hero.sh > /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: diff --git a/aiprompts/herolib_advanced/advanced_paths.md b/aiprompts/herolib_advanced/advanced_paths.md new file mode 100644 index 00000000..630cc717 --- /dev/null +++ b/aiprompts/herolib_advanced/advanced_paths.md @@ -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. \ No newline at end of file diff --git a/aiprompts/herolib_advanced/redis.md b/aiprompts/herolib_advanced/redis.md new file mode 100644 index 00000000..bea288fc --- /dev/null +++ b/aiprompts/herolib_advanced/redis.md @@ -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}') \ No newline at end of file diff --git a/aiprompts/herolib_core/core_paths.md b/aiprompts/herolib_core/core_paths.md new file mode 100644 index 00000000..7a04b9e9 --- /dev/null +++ b/aiprompts/herolib_core/core_paths.md @@ -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 +} +``` + diff --git a/aiprompts/herolib_core/core_vshell.md b/aiprompts/herolib_core/core_vshell.md index 99476e8e..ce06efec 100644 --- a/aiprompts/herolib_core/core_vshell.md +++ b/aiprompts/herolib_core/core_vshell.md @@ -15,3 +15,4 @@ the files are in ~/code/github/freeflowuniverse/herolib/examples for herolib - never use fn main() in a .vsh script - always use the top line as in example above +- these scripts can be executed as is but can also use vrun $pathOfFile diff --git a/aiprompts/herolib_core/example_script_curdir.md b/aiprompts/herolib_core/example_script_curdir.md new file mode 100644 index 00000000..bfc230e2 --- /dev/null +++ b/aiprompts/herolib_core/example_script_curdir.md @@ -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}" + +``` \ No newline at end of file diff --git a/aiprompts/herolib_start_here.md b/aiprompts/herolib_start_here.md index 6eef01a0..4c8e26e6 100644 --- a/aiprompts/herolib_start_here.md +++ b/aiprompts/herolib_start_here.md @@ -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 - 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 diff --git a/aiprompts/v_advanced/compress.md b/aiprompts/v_advanced/compress.md new file mode 100644 index 00000000..6e8f79d9 --- /dev/null +++ b/aiprompts/v_advanced/compress.md @@ -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. \ No newline at end of file diff --git a/examples/biztools/bizmodel_complete.vsh b/examples/biztools/bizmodel_complete.vsh new file mode 100755 index 00000000..aa8a89d3 --- /dev/null +++ b/examples/biztools/bizmodel_complete.vsh @@ -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)! diff --git a/examples/biztools/examples/complete.heroscript b/examples/biztools/examples/complete.heroscript new file mode 100644 index 00000000..308015f6 --- /dev/null +++ b/examples/biztools/examples/complete.heroscript @@ -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' \ No newline at end of file diff --git a/examples/compress_gzip_example.vsh b/examples/compress_gzip_example.vsh new file mode 100644 index 00000000..e5e17b84 --- /dev/null +++ b/examples/compress_gzip_example.vsh @@ -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.') +} \ No newline at end of file diff --git a/install_herolib.vsh b/install_herolib.vsh index f010ec47..2e027ccf 100755 --- a/install_herolib.vsh +++ b/install_herolib.vsh @@ -68,7 +68,10 @@ addtoscript('alias vtest=', 'alias vtest=\'v -stats -enable-globals -show-c-outp 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 { eprintln('Failed to add path to hero, ${err}')