sfw-tools

Design

In the spirit of Software Tools, the aim is to make components re-usable in three ways:

  1. Implement core features as functions, so they can be re-used within Rust. These functions should generally return a Result type, so the caller can decide how to deal with the error.
  2. Executable commands with a simple interface that typically act as thin wrappers around the library functions, or perhaps combine the library functions in interesting ways.
  3. As well designed code that can be copied as repurposed when necessary.

A fourth avenue may be explored, which is to adopt the nushell approach to transfering tabular data between commands.

For a related project that also follows Software Tools in Rust, and may serve as an interesting comparison, see Sweater. A more feature-rich project is uutils coreutils, which as the name suggests, is a Rust implementation analogous to GNU Coreutils.

Functional facilities

Higher-order-functions (HOFs) are frequently used to reduce code complexity, verbosity, and the risk of errors. Primary examples are map, for_each (like map but effectful), and fold. As pointed out in Software Tools, pp 21, "The best programs are designed in terms of loosely coupled functions that each does a simple task."

Currently Implemented Tools

Dependencies

Since the goal is to make the software both as self-contained and as illustrative as possible, we've tried to rely on very few dependencies. The following exceptions exist:

Currently unused

Build

Misc Notes

Using todo!() to

Using todo!() from std::todo is a helpful way to incrementally develop a feature while still getting feedback from the compiler. [TODO: show example]

A caveat is that currently you need code in the function after the todo!(), even if it doesn't match the type. For instance, we can use a function like:

rust pub fn some_num() -> i32 { todo!(); (); }

Most beneficial is that rustc will warn you if you a todo!() is left in your code, since it would result in a panic if that execution path were to occur.

Rust on nix

```plain nix-shell -p rustup cargo

```

Optimizing for size

Currently, to generate small builds the following commands are required.

  1. (only once per environment) Make source code for the standard library available:

plain rustup component add rust-src --toolchain nightly

2.

plain cargo +nightly build -Z build-std --target x86_64-unknown-linux-gnu --release

  1. (optional) strip binary - see links in notes

Project administration

Git hooks

Cargo-Husky

We use cargo-husky to keep in line; it enforces several checks with a pre-push hook. Sometimes it is a bit restrictive, so if we need to push in-progress work to a branch, we can use git push --no-verify -u origin feature_branch. Cargo-husky expects certain files to be at the root of the repository, thus the symlinks.

pre-commit

We include the following, less stringent checks for pre-commit.

```bash

!/bin/sh

Put in your Rust repository's .git/hooks/pre-commit to ensure you never

breaks rustfmt.

#

WARNING: rustfmt is a fast moving target so ensure you have the version that

all contributors have.

for FILE in git diff --cached --name-only; do if [[ -f "$FILE" ]] && [[ $FILE == *.rs ]] \ && ! rustup run nightly rustfmt --unstable-features \ --skip-children $FILE; then echo "Commit rejected due to invalid formatting of \"$FILE\" file." exit 1 fi done

cd Rust/sfw-tools && cargo readme > README.md && git add README.md `` As can be seen this also gnerates the README from doc comments inlib.rs`.

License: MPL-2.0