This is a revised and expanded version of a post which originally appeared in the 2023 Perl Advent Calendar.
"Typewriter Eraser, Scale X" by ChrisYunker is licensed under CC BY 2.0 .
When you’re constantly producing code and documentation, mistakes will happen. Some will be easy to spot and others may elude you. We know that attention to detail counts. When someone finds a typo in your documentation or your code, they may be inclined to ask themselves what else may be wrong. In order to avoid the impression of carelessness, let’s automate the finding and fixing of typos.
The Tool#
One of the tools which we have in our toolkit is the
typos utility. The wonderful thing about
typos
is that this Rust-based tool can improve code and documentation in many
different languages. It’s that good!
How it Works#
From the docs:
typos maintains a list of known typo corrections to keep the false positive count low so it can safely run unassisted.
This is in contrast to most spell checking UIs people use where there is a known list of valid words. In this case, the spell checker tries to guess your intent by finding the closest-looking word. It then has a gauge for when a word isn’t close enough and assumes you know best. The user has the opportunity to verify these corrections and explicitly allow or reject them.
Getting Set Up#
After installing typos
, it’s trivial to spot typos in code.
$ typos
[some output appears]
That’s it! Now, let’s try it on the Perl Advent Calendar. We’ll start with the articles in 2019. This gives us all sorts of helpful information.
$ typos 2019
error: `entires` should be `entries`
--> 2019/articles/2019-12-16.pod:253:23
|
253 | And start adding todo entires:
| ^^^^^^^
|
error: `hightlight` should be `highlight`
--> 2019/articles/2019-12-14.pod:113:56
|
113 | # work out the three strings (left of / before hightlight,
| ^^^^^^^^^^
|
error: `hightlight` should be `highlight`
--> 2019/articles/2019-12-14.pod:114:24
|
114 | # the middle / hightlight, and then right of / after highlight)
| ^^^^^^^^^^
|
error: `assing` should be `assign`
--> 2019/articles/2019-12-14.pod:121:27
|
121 | # what we want to assing to $x so we start drawing there again.
There are actually a few more typos, but this is a good demonstration of what we might find. Now, how do we fix it?
$ typos -w 2019
error: `fils` should be `fills`, `files`, `file`
--> 2019/articles/2019-12-20.pod:136:59
|
136 | if that machine can access the internet, if I can put the fils in my home
| ^^^^
|
error: `whe` should be `when`, `we`
--> 2019/articles/2019-12-19.pod:25:17
|
25 | between runs.", whe Wise Old Elf explained sagely, "Then you'd be able to
| ^^^
|
This actually fixes a number of typos, but there are two which the tool cannot resolve, so it makes some suggestions for us to use in a manual fix.
This leaves the matter of how many changes were actually made. Let’s see:
$ git diff --stat 2019
2019/articles/2010-12-11.pod | 2 +-
2019/articles/2019-12-04.pod | 2 +-
2019/articles/2019-12-05.pod | 4 ++--
2019/articles/2019-12-07.pod | 4 ++--
2019/articles/2019-12-10.pod | 2 +-
2019/articles/2019-12-12.pod | 2 +-
2019/articles/2019-12-13.pod | 8 ++++----
2019/articles/2019-12-14.pod | 6 +++---
2019/articles/2019-12-16.pod | 2 +-
2019/articles/2019-12-18.pod | 6 +++---
2019/articles/2019-12-20.pod | 4 ++--
2019/articles/2019-12-21.pod | 4 ++--
2019/articles/2019-12-22.pod | 2 +-
2019/articles/2019-12-24.pod | 2 +-
14 files changed, 25 insertions(+), 25 deletions(-)
We can now go over the changes individually via git add -p
and we’ll find
that all but one seem to be correct. 24 typos found and fixed in 47 ms. That’s
not bad at all.
As we process more and more files, we will likely find some false positives
which we want to correct. This can be done in a config file. Ours is
typos.toml
.
[default.extend-words]
ANDed = "ANDed"
ba = "ba"
Claus = "Claus"
DNE = "DNE"
IFF = "IFF"
Signes = "Signes"
[files]
extend-exclude = ["advent.ini", "data.en"]
In order to skip false positives, we add words to the default.extend-words
section. Yes, it’s kind of a surprising way to do this, but let’s go along with
it. Also, any files which we don’t want to check can be added to
extend-include
in the [files]
section.
More Than Just Documentation#
typos 2019
The neat thing about typos
is that it can also fix things in your code itself
and not just the documentation.
Imagine we have a Perl script with the following contents:
use strict;
use warnings;
sub widht {}
my $strng = 'foo';
What does typos
have to say about it?
$ typos workshop.pl
error: `widht` should be `width`
--> workshop.pl:4:5
|
4 | sub widht {}
| ^^^^^
|
error: `strng` should be `string`
--> workshop.pl:6:5
|
6 | my $strng = 'foo';
| ^^^^^
|
We can see that our function name and our variable name have been caught and
will be corrected if we run again with typos -w
.
Digging Deeper#
Beyond the basics of typos
and typos -w
, we can do more. Let’s touch on a
few things now, but you can always check typos --help
for a more complete
list of options.
--words
#
typos
does its best to find words not only in your documentation, but also in
your code. If you’re scratching your head as to why a certain word is not being
flagged, you can use the --words
flag to see a list of words in your project
which are being checked. Maybe it’s not being discovered?
typos --words
To get a more readable list: typos --words | sort | uniq
To do some fuzzy matching on the list, pipe the results to fzf
:
typos --words | sort | uniq | fzf
If you’re not familiar with fzf
, you may find some of my fzf
articles to be helpful.
--locale
#
Are you tired of typos
telling you that the Queen’s (King’s?) English is
wrong? You can change the locale to en-gb
and you can once again feel at one
with the universe.
The currently available locales are: en
, en-au
, en-ca
, en-gb
and en-us
.
typos --locale en-gb
--diff
#
Would you like to see a diff before you run typos -w
? You can do that via
typos --diff
Going back to our previous example:
typos --diff foo.pl
--- foo.pl original
+++ foo.pl fixed
@@ -3,2 +3,2 @@
-sub widht {}
-my $strng = 'foo';
+sub width {}
+my $string = 'foo';
Integrations#
Neovim#
Users of Neovim can also enable typos
linting via
https://github.com/mfussenegger/nvim-lint
VS Code#
There is also a VS Code
extension
for typos
. I’m not in VS Code very often, so I haven’t tested this myself,
but that looks to be worth exploring.
LSP#
If you prefer the Language Server Protocol (LSP), there is also an LSP integration, which is part of the VS Code extension above.
precious#
If you use precious as a harness around your linters and tidiers, you can start by adding this to your configuration.
[commands.typos]
type ="both"
include = ["**/*"]
cmd = ["typos"]
tidy_flags = ["-w"]
ok_exit_codes = 0
If you haven’t tried precious
, I highly recommend it. I’ll be digging a bit
deeper into this tool in a forthcoming post. You may subscribe to email updates
using the form at the bottom of this post, if you don’t want to miss it.
Now We Look Smart(er)#
Having discovered this very useful tool, we can add it to our linters and
fixers, make it part of our pre-commit
hooks and include it in our Continuous
Integration configuration.
For those of us who enjoy creating a quick pull request to fix someone else’s typos, we can now employ this tool on repositories which we have just checked out. A helpful pull request for a grateful maintainer 🙏 is just minutes away.
As one more data point, I used typos
to check this very article and I’m both
proud and ashamed to say that it found more than one problem. 😅
typos
will not find all errors, but it will find issues which are hard for
the human eye to spot. It’s not a replacement for a code review, but it’s a
helpful tool to have in your toolbox for the days when you just
don’t see the typos which are staring you in the face. The best part is, you
get to find the typos before someone else does. 🥳