Jim Tcl in Rust
This is the documentation site for the rust-jim project, which supplies two things:
- The
jimtclcrate, and its underlyingjimtcl-sys, to enable Jim Tcl to be embedded in Rust programs. - Guardian Tcl, an extended version of Jim Tcl with additional commands leveraging the rich Rust ecosystem.
The rust-jim repository on Codeberg has the source code and issue tracker. Pull requests welcome!
Embedding Jim Tcl
The jimtcl crate is the primary entry point to embed stock Jim Tcl into Rust.
It uses the separate jimtcl-sys crate that provides the Jim Tcl source code
and low-level FFI bindings.
The API reference is the primary documentation for using this crate.
Jim is compiled and statically linked into the executable. Linking against a system-provided Jim is TBD.
Note
Currently, Jim Tcl only supports Unix-like systems. Windows suppport is planned but not yet implemented.
Crate Features
The following features control Rust integration, and are enabled by default:
cli— add a dependency onClapand provide a reusable command line for Jim Tcl shells. Enables therust-jimshbinary as well.serde— add aDeserializeSeedimplementation to allow Jim objects to be directly deserialized with Serde format libraries. Serialization is not yet supported, as it would require some kind of schema mechanism.
Extension Features
Each of the Jim Tcl optional extensions, except for database extensions, is
exposed through a Rust crate feature, and passed through to a correpsonding
feature on jimtcl-sys. They are all enabled by default.
- aio
- array
- binary
- clock
- ensemble
- eventloop
- exec
- file
- glob
- history
- interp
- json (enables both
jsonandjsonencodeextensions) - namespace
- oo
- pack
- package
- posix
- readdir
- regexp
- signal
- tclcompat
- tree
Introducing Guartcl
Guardian is Jimmy Olsen with superhero gear.
Guartcl is Jim Tcl with extra bits.
Guardian Tcl is provided by the guartcl crate, and supplies a guarsh binary
to run Guardian Tcl scripts.
Guardian uses Jim with all default extensions enabled, except for SSL. For full details on the Jim Tcl commands, see Jim Tcl manual. These pages only document Guardian’s extensions to Jim Tcl.
Installing
Guardian Tcl release binaries can be downloaded from Codeberg. The
easiest way to install them is with cargo-binstall:
$ cargo binstall guartcl
It also works well to install Guardian with Mise. Add the following to your
mise.toml or mise/config.toml:
[tools."forgejo:mdekstrand/rust-jim"]
version = "latest"
matching = "guartcl"
Command-Line Parsing
Guardian Tcl supports command-line parsing with Usage, a suite for parsing
command line arguments and generating documentation from a spec that can be
embedded as #USAGE comments in the top of a script file.
When run with the -U or --usage flag and a script, guarsh will use Usage
to parse the script’s command-line arguments and store the results of this parse
in the usage Tcl array. This is equivalent to the parsing done with usage bash, usage exec, or similar, with a few differences:
- The results of parsing the arguments are stored in a Tcl array1 named
usageinstead of environment variables. - Repeated arguments are stored as Tcl lists instead of shell-quoted strings.
- Boolean and count flags are always set in the array, with a value of 0 if they do not appear.
-
Actually a dictionary in the
usagevariable, but in Jim Tcl arrays and dict variables are the same thing. ↩
Commands
Guardian Tcl currenly adds one ensemble command, parse. This command
exposes subcommands to parse data from a variety of formats directly into nested
Tcl data structures.
parse
The parse command has the following usage:
parse <format> <data>
parse <format> -file <path>
<format>can be any ofjson,toml, oryaml.<data>is a Tcl string containing the raw data to deserialize.<path>is the path to a file containing data in the specified format.
For example, to deserialize the contents of the $conf_src variable as JSON,
you can write:
set config [parse json $conf_src]
These commands are wrappers around the corresponding Serde deserializers. You
can also parse by parsing to typedata and using td native to
obtain a native Tcl structure.
uuid
The uuid ensemble can generate and inspect UUIDs (backed by the uuid crate).
UUIDs are represented as hexadecimal strings without braces.
- uuid v3 namespace name
- Generate a version 3 (MD5) UUID with the specified namespace and name. namespace can be either a UUID, or one of the strings
oid,url,dns, orx500. - uuid v4
- Generate a version 4 (random) UUID.
- uuid v5 namespace name
- Generate a version 5 (SHA1) UUID. Parameters are identical to
uuid v3. - uuid v7
- Generate a version 7 (timestamp + random, sortable) UUID.
- uuid version uuid
- Query the version number of the specified UUID.
- uuid timestamp uuid
- Query the timestamp of the specified UUID (v1, v6, or v7).
- uuid random
- Generate a random UUID (currently alias for
uuid v4). - uuid bytes
- Obtain the binary representation of the UUID as a 16-byte binary string.
Binary Extensions
Guardian Tcl extends the binary ensemble with binary encode and binary decode commands. These function much like the standard Tcl binary encode/decode
commands1, except they do not support any options.
- binary encode encoding data
- Encode data with encoding.
- binary decode encoding data
- Decode data with encoding.
It also provides a command to generate random bytes:
- binary random n
- Generate n random bytes as a binary string. This uses the system’s (secure) random number generator via getrandom.
Supported Encoding
The following encodings are supported:
- base64 (using data-encoding)
- base32 (using data-encoding)
- hex (using data-encoding)
- base58 (using bs58)
Type Data (td)
Note
These commands are only available in Guardian Tcl 0.5 or later, which is currently in prerelease.
Guardian Tcl provides a “typed data” structure, accessed through the td
ensemble command, that represents JSON-like data along with type information,
instead of Tcl’s usual string-based representation. It is similar in that
respect to Huddle, but uses JSON as its string representation and checks
types in Rust. You can think of it as a native-code Huddle, however. Any valid
JSON string is a valid TypedData object.
Note
JSON is the string representation as of 0.5, but this may change in the future if we find a need for data types not supported by JSON.
Creating Typed Data
The following commands create a typed data value:
- td null
- Create a null value.
- td boolean val
- Create a boolean value. val is any valid Tcl boolean.
- td integer n
- Create an integer value with value n.
- td float x
- Create a floating-point value with value x.
- td string str
- Create a string value with value str.
- td list value…
- Create a list value with the value(s) provided as arguments. The list elements themselves must already be typed data.
- td record key value …
- Create a record (dictionary) value with the key-value pairs provided as arguments (works like
dict create). The values themselves must already be typed data.
Conversion
- td native td
- Convert the typed data td to Tcl-native layout (values, lists, and dicts).
- td coalesce td …
- Return the first non-null argument.
Conversion to native is not directly reversible, because Tcl-native format loses the type information from the original.
Since typed data is stored as JSON, use the Jim Tcl json::encode command to convert Tcl-native data to JSON.
Querying Typed Data
These commands all query typed data, and require the typed data itself as input.
- td get ?-native? td key…
- Traverses the typed data td by the specified keys path to query an record. The first key is looked up in td, the second in the first key’s value, and so forth. Keys can be strings for records, or valid indices for lists. The full Tcl list index syntax (e.g.
end,end-1) is supported. - td type td
- Get the type of the typed data value.
- td length td
- Get the length of the typed data value if it is a record, list, or string. Fails for other types of data.
Manipulating Typed Data
Unlike the other typed-data functions, these commands take a tdvar parameter specifying the name of the variable storing the typed data to manipulate.
Important
Typed data values are effectively immutable, and manipulating typed data updates the variable to store a new typed data. In particular, using these functions on the result of a
td getcommand will not modify the original data structure thattd getqueried.
- td set tdvar key… value
- Update the location in the record specified by the key path to store value. If a key does not exist in a record value, it will be added (this does not work for lists).
- td lappend tdvar key… ?–? value…
- Append the specified values to the list addressed by the key path. Fails if the key path does not specify a list. Separating the key path from the values with
--is required if you want to add more than one value to the list.
Data Format Interchange
Parsing
- td parse json ?-file? input
- Parse the specified JSON input as typed data. Since typed data is represented as JSON, this just validates the input. The
-fileoption instructs it to treat input as a filename instead of JSON text. - td parse yaml ?-file? input
- Just like
td parse json, except it parses YAML. - td parse toml ?-file? input
- Just like
td parse json, except it parses TOML.
Dumping
Typed data can also be dumped to several formats.
- td dump json ?-pretty? ?-file outfile? td
- Save the typed data as JSON, optionally to a file, optionally with pretty-printing. The file is saved with a terminating newline in either case.
- td dump toml ?-pretty? ?-file outfile? td
- Save the typed data as TOML, optionally to a file, optionally with pretty-printing.
- td dump yaml ?-file outfile? td
- Save the typed data as TOML, optionally to a file.
Compiling Binaries
Note
This is an upcoming feature in Guardian Tcl 0.6.
Guardian Tcl supports building stand-alone executables containing both the Tcl
interpreter and a Tcl script. This functionality is exposed through the
guardian::compile Tcl command. It is intended to function somewhat like
Tclkits for OG Tcl, but is more limited and based on Jim Tcl with the Guardian
extensions.
Note
Standalone executables are currently missing several features, most notably
package require.
- guardian::compile ?-usage? ?-out exe? script
- Compile script (the path to a Tcl file, not a Tcl script string) into a standalone executable. If
-outis not specified, the output name is derived from the script name.-usageenables CLI parsing based on Usage specifications embedded in the script.