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.
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).
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.
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.
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.