simplint
simplint is a lint for Simplified Technical English (ASD-STE100). It reads the comments and docstrings in source files, and Markdown files as prose. It tells you which words and sentences do not follow the standard.
Each finding gives the file, the position, the severity, the message and the rule:
$ simplint check
foo.py:2:29: error: 'ensure' is not approved; use 'make sure' [STE 1.1]
foo.py:3:7: error: 'don't' is a contraction; write the words in full [STE 4.2]
foo.py:3:13: error: 'delve' is not in the STE dictionary; if it is a technical name, add it to simplint.toml [STE 1.6]
foo.py:4:7: error: sentence has 28 words; the STE limit for descriptive text is 25 [STE 6.3]
foo.py:4:7: error: 'closing' is the -ing form of 'close'; STE allows only the infinitive, imperative, past tense and past participle [STE 3.5]
The exit code is 1 when there is an error.
Installing
ASD-STE100 is copyrighted, thus the binary does not contain its dictionary. The first run downloads the PDF from ASD and makes the vocabulary in ~/.cache/simplint/. The Nix package makes it when it builds.
On your machine
Use the install script, or use Nix.
The install script
The release binaries are for Linux and macOS, on x86_64 and aarch64:
curl -fsSL https://simplint.antimemetics.institute/install.sh | sh
simplint check
Nix
With Nix, there is no installation. This builds the checker with the vocabulary and with each tree-sitter grammar that nixpkgs has, and runs it:
$(nix-build --no-out-link \
https://github.com/antimemes/simplint/archive/main.tar.gz)\
/bin/simplint check
With flakes:
nix run github:antimemes/simplint -- check
In GitHub Actions
Put this in .github/workflows/simplint.yml. The findings become annotations on the pull request:
name: simplint
on:
push:
branches: [main]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: antimemes/simplint@latest
Configuration
simplint reads simplint.toml at the project root. Each key is optional. The first line gives your editor the schema:
#:schema https://raw.githubusercontent.com/antimemes/simplint/main/crates/simplint/simplint.schema.json
profile = "strict" # "strict" or "basic"
words = ["gantry", "sprocket"]
word-lists = ["words.txt", "https://example.com/team-words.txt"]
default-word-lists = true
ignore = ["vendor/", "*.generated.go"]
[rules]
"6.3" = "warning" # "error", "warning" or "off"
[languages.rust] # for the files of one language
words = ["monomorphize"]
word-lists = ["rust-words.txt"]
default-word-lists = true
[languages.rust.rules]
"1.6" = "off"
| Key | Effect |
|---|---|
profile | the severity of each rule, see Rules |
rules | the severity of one rule |
words | the technical names and verbs of the project, see Words |
word-lists | files, URLs and bundled lists of words |
default-word-lists | use the bundled lists (default: true) |
ignore | paths that simplint does not examine, in the syntax of .gitignore |
languages.<name> | the same keys for the files of one language, see Languages |
Words
The ASD-STE100 dictionary has approximately 900 words. The technical names and technical verbs of your domain are not in it, and the standard lets you use them. Tell simplint which they are:
words: a list insimplint.toml.word-lists: files with one word on each line and#comments. An entry is a path from the directory ofsimplint.toml, a URL, or the name of a bundled list.default-word-lists: the bundled lists are on unless this isfalse. Thesoftwarelist applies to all files, and the list of a language to its files.
The entries add to each other. simplint accepts a listed word with its usual inflections: the plural, -ed and -ing.
simplint fetch downloads the URLs into ~/.cache/simplint/words/, and simplint check reads them from there.
The bundled lists are software, c, cpp, go, java, javascript, markdown, nix, python, rust, toml, tsx and typescript. Their text is in the repository.
To use only your lists:
default-word-lists = false
word-lists = ["words.txt"]
Rules
ASD-STE100 Issue 9 has 53 rules. A program can check a part of them. simplint checks these:
| Rule | Finding |
|---|---|
| 1.1 | a word that is not approved, with the approved alternatives, for example commence (use start) |
| 1.2 | an approved word in a part of speech in which it is not approved. For example, test is a noun, thus “do a test” and not “test it” |
| 1.6 | a word that is not in the dictionary and not in your word list, for example kubelet. Put the words of your project in simplint.toml, and they are approved |
| 3.5 | the -ing form of an approved verb, for example starting |
| 4.2 | a contraction, for example don't |
| 6.3 | a sentence of more than 25 words |
Each rule has a severity: error, warning or off. The exit code is 1 when there is an error. The profile sets the severity of each rule:
| Profile | Effect |
|---|---|
strict (the default) | each finding is an error |
basic | 1.6 and 6.3 are warnings |
[rules] changes one rule, and [languages.<name>.rules] changes it for the files of one language. The language value applies first, then [rules], then the profile:
profile = "basic"
[rules]
"4.2" = "off"
[languages.markdown.rules]
"1.6" = "off"
A rule that gives no findings cannot be set. simplint stops with an error message when it reads simplint.toml.
Languages
simplint lints each language that has a tree-sitter grammar. The grammar name is the key of [languages.<name>], for example rust, python, cpp or markdown.
Rust, Python, JavaScript, TypeScript, Go, C, Java, Nix, TOML and Markdown are compiled in. For each other language simplint loads <name>.so from a grammar directory, in this sequence:
--grammars <dir>- each directory in
SIMPLINT_GRAMMARS ~/.local/share/simplint/grammars
These are the grammar files that Neovim and nixpkgs make. The Nix package sets SIMPLINT_GRAMMARS to all the grammars in nixpkgs. When a file has no grammar, simplint does not examine it, and gives a note at the end.
A [languages.<name>] table has the keys words, word-lists, default-word-lists and rules, for the files of that language.
Markdown files are prose. simplint reads their paragraphs, headings and table cells, and not their code blocks.