Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Jim Tcl in Rust

This is the documentation site for the rust-jim project, which supplies two things:

  • The jimtcl crate, and its underlying jimtcl-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 on Clap and provide a reusable command line for Jim Tcl shells. Enables the rust-jimsh binary as well.
  • serde — add a DeserializeSeed implementation 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 json and jsonencode extensions)
  • 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 usage instead 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.

  1. Actually a dictionary in the usage variable, 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 of json, toml, or yaml.
  • <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 -file option 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 get command will not modify the original data structure that td get queried.

td set tdvar keyvalue
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.