published on in fzf linting Neovim precious tidying typos VS Code

Find and Fix More Typos

âŦ…ī¸ Previous post: Using Tig to Make Sense of Git

❤ī¸ It's great to see you here! I'm currently available on evenings and weekends for consulting and freelance work. Let's chat about how I can help you achieve your goals.



This is a revised and expanded version of a post which originally appeared in the 2023 Perl Advent Calendar.

splash

"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

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. đŸĨŗ