diff --git a/docs/book.toml b/docs/book.toml index 58d2a283..4913a6f7 100644 --- a/docs/book.toml +++ b/docs/book.toml @@ -1,11 +1,11 @@ [book] -authors = ['nomoi.xyz'] src = 'src' -title = 'Vulcan Book' +title = '' [output.html] +no-section-label = true additional-js = ['solidity.min.js'] additional-css = ['book.css'] -git-repository-url = 'https://github.com/nomoixyz/vulcan' +git-repository-url = 'https://github.com/foundry-rs/foundry' [output.html.fold] enable = true diff --git a/docs/src/README.md b/docs/src/README.md index facf2273..0d9b4ff2 100644 --- a/docs/src/README.md +++ b/docs/src/README.md @@ -10,9 +10,6 @@ Initially, Vulcan will provide functionality similar to what is already included Over time, Vulcan will grow to include more functionality and utilities, eventually becoming a feature-rich development framework. -> **Warning** -> This library should be treated as highly experimental, its API WILL change, and there might be bugs in it. Don't use in production yet. - ## Why Vulcan? Our goal is to provide: diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 53c5111e..d3e79c2f 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -14,11 +14,13 @@ - [Context](./modules/context.md) - [Env](./modules/env.md) - [Events](./modules/events.md) + - [Format](./modules/fmt.md) - [Forks](./modules/forks.md) - [Fs](./modules/fs.md) - [Huff](./modules/huff.md) - [Json](./modules/json.md) - [Strings](./modules/strings.md) + - [Utils](./modules/utils.md) - [Watchers](./modules/watchers.md) # Reference @@ -30,6 +32,7 @@ - [Context](./reference/modules/context.md) - [Env](./reference/modules/env.md) - [Events](./reference/modules/events.md) + - [Format](./reference/modules/fmt.md) - [Forks](./reference/modules/forks.md) - [Fs](./reference/modules/fs.md) - [Huff](./reference/modules/huff.md) diff --git a/docs/src/guide/installation.md b/docs/src/guide/installation.md index 3897762f..7e930118 100644 --- a/docs/src/guide/installation.md +++ b/docs/src/guide/installation.md @@ -2,5 +2,5 @@ In an existing Foundry project, use `forge install`: ``` -$ forge install nomoixyz/vulcan@alpha-1 +$ forge install nomoixyz/vulcan@0.1.0 ``` diff --git a/docs/src/modules/fmt.md b/docs/src/modules/fmt.md new file mode 100644 index 00000000..ebfb5ebf --- /dev/null +++ b/docs/src/modules/fmt.md @@ -0,0 +1,24 @@ +# Format + +The format function defined under the `fmt` module enables you to format strings dynamically by using a template string and the ABI encoded arguments: + +```solidity +import {Test, expect, console, fmt} from "vulcan/test.sol"; + +contract TestMyContract is Test { + function testFormat() external { + string memory template = "{address} hello {string} world {bool}"; + + // You can also use abbreviations: "{a} hello {s} world {b}"; + template = "{a} hello {s} world {b}"; + + string memory result = fmt.format(template, abi.encode(address(123), "foo", true)); + expect(result).toEqual("0x000000000000000000000000000000000000007B hello foo world true"); + + // For numerical values, you can even specify the number of decimals to format with + expect(fmt.format("{uint:d18}", abi.encode(1e17))).toEqual("0.1"); + } +} +``` + +This example demonstrates the use of a string template with placeholders and a custom formatting function to generate a formatted string. It is a simple and efficient way to manage dynamic values on strings. \ No newline at end of file diff --git a/docs/src/modules/strings.md b/docs/src/modules/strings.md index c62ebfb3..09d71a20 100644 --- a/docs/src/modules/strings.md +++ b/docs/src/modules/strings.md @@ -27,6 +27,10 @@ contract TestMyContract is Test { // Parse an address string to an `address` expect("0x13DFD56424777BAC80070a98Cf83DD82246c2bC0".parseAddress()).toEqual(0x13DFD56424777BAC80070a98Cf83DD82246c2bC0); + + // Format - see the Format module for more details + uint256 amount = 1e17; + expect("Token amount: {u:d18}".format(abi.encode(amount))).toEqual("Token amount: 0.1"); } } ``` diff --git a/docs/src/modules/utils.md b/docs/src/modules/utils.md new file mode 100644 index 00000000..e987813e --- /dev/null +++ b/docs/src/modules/utils.md @@ -0,0 +1,20 @@ +# Utils + +This module provides a set of utility functions that make use of other modules in Vulcan. + +```solidity +import {Test, expect, println, format} from "vulcan/test.sol"; + +contract TestMyContract is Test { + function testUtils() external { + // Print a string + println("Hello world!"); + + // Print a formatted string - see Format module for more details + println("Hello {string}!", abi.encode("world")); + + // Format a string + expect(format("Hello {string}!", abi.encode("world"))).toEqual("Hello world!"); + } +} +``` \ No newline at end of file diff --git a/docs/src/reference/modules/fmt.md b/docs/src/reference/modules/fmt.md new file mode 100644 index 00000000..6e29bd48 --- /dev/null +++ b/docs/src/reference/modules/fmt.md @@ -0,0 +1,29 @@ +# Format + +#### **`format(string template, bytes args) → (string)`** + +## Template Reference + +The template is a string that can contain placeholders for the arguments. The placeholders are defined by curly braces `{}` and can be of the following types: + +- **Address**: `{address}` or `{a}` +- **Bytes32**: `{bytes32}` or `{b32}` +- **String**: `{string}` or `{s}` +- **Bytes**: `{bytes}` or `{b}` +- **Uint**: `{uint}` or `{u}` +- **Int**: `{int}` or `{i}` +- **Boolean**: `{bool}` + +### Modifiers + +Some placeholder types can be followed by a colon `:` and a format specifier. The format specifier is a single character that defines how the argument should be formatted, and can also contain additional arguments. The following format specifiers are supported: + +#### Decimals (`dX`) + +Supported types: `uint`, `int` + +Formats the provided value to a string representation that uses the specified amount of decimals. One of the main use cases is to format token amounts. + +Examples: +- `{uint:d18}` formats the value `1e18` to `"1.0"` +- `{uint:d2}` formats the value `10` to `"0.1"` diff --git a/docs/src/reference/modules/strings.md b/docs/src/reference/modules/strings.md index 9e762708..2672144d 100644 --- a/docs/src/reference/modules/strings.md +++ b/docs/src/reference/modules/strings.md @@ -1,30 +1,34 @@ # Strings -#### **`toString(address value) → (string )`** +#### **`format(string template, bytes args) public → (string)`** + +See [**Format API reference**](./fmt.md) for more details. + +#### **`toString(address value) → (string)`** Transforms an address to a string. -#### **`toString(bytes value) → (string )`** +#### **`toString(bytes value) → (string)`** Transforms a byte array to a string. -#### **`toString(bytes32 value) → (string )`** +#### **`toString(bytes32 value) → (string)`** Transforms a bytes32 to a string. -#### **`toString(bool value) → (string )`** +#### **`toString(bool value) → (string)`** Transforms a boolean to a string. -#### **`toString(uint256 value) → (string )`** +#### **`toString(uint256 value) → (string)`** Transforms an uint256 to a string. -#### **`toString(int256 value) → (string )`** +#### **`toString(int256 value) → (string)`** Transforms an int256 to a string. -#### **`parseBytes(string value) → (bytes )`** +#### **`parseBytes(string value) → (bytes)`** Parses a byte array string. diff --git a/src/_modules/Commands.sol b/src/_modules/Commands.sol index bb356bf6..577457ed 100644 --- a/src/_modules/Commands.sol +++ b/src/_modules/Commands.sol @@ -119,6 +119,25 @@ library commands { return self.args(_toDynamic(_args)); } + /// @dev Transforms a command to its string representation. + /// @param self The command struct that will be transformed to a string. + /// @return The string representation of the command. + function toString(Command memory self) internal pure returns (string memory) { + string memory output; + + uint256 length = self.inputs.length; + + for (uint256 i; i < length; ++i) { + output = string.concat(output, self.inputs[i]); + + if (i < length - 1) { + output = string.concat(output, " "); + } + } + + return output; + } + /// @dev Runs a command using the specified `Command` struct as parameters and returns the result. /// @param self The `Command` struct that holds the parameters of the command. /// @return The result of the command as a bytes array. diff --git a/test/_modules/Accounts.t.sol b/test/_modules/Accounts.t.sol index 6b9b4d6c..93f19311 100644 --- a/test/_modules/Accounts.t.sol +++ b/test/_modules/Accounts.t.sol @@ -28,7 +28,7 @@ contract AccountsTest is Test { } function testItCanSetTheCode() external { - address addr = address(1); + address addr = address(1337); Sender sender = new Sender(); diff --git a/test/_modules/Commands.t.sol b/test/_modules/Commands.t.sol index 4b95a978..07385627 100644 --- a/test/_modules/Commands.t.sol +++ b/test/_modules/Commands.t.sol @@ -18,4 +18,10 @@ contract CommandsTest is Test { expect(string(output)).toEqual(inputs[1]); } + + function testCommandToString() external { + Command memory ping = commands.create("ping").args(["-c", "1", "nomoi.xyz"]); + + expect(ping.toString()).toEqual("ping -c 1 nomoi.xyz"); + } }