All four of them are movement based on a character. Let’s see what :help tells us about them.

f{char}  To [count]'th occurrence of {char} to the right.  The
         cursor is placed on {char} |inclusive|.
         {char} can be entered as a digraph |digraph-arg|.

F{char}  To the [count]'th occurrence of {char} to the left.
         The cursor is placed on {char} |exclusive|.
         {char} can be entered like with the |f| command.

t{char}  Till before [count]'th occurrence of {char} to the
         right.  The cursor is placed on the character left of
         {char} |inclusive|.
         {char} can be entered like with the |f| command.

T{char}  Till after [count]'th occurrence of {char} to the
         left.  The cursor is placed on the character right of
         {char} |exclusive|.
         {char} can be entered like with the |f| command.

We can see lower case version moved forward, while the upper case letter moves backwards.

While t/T moves to the character, but stops before that specific character, f/F places the cursor on the character.

An easy way to remember which one is which:

  • t to move to the character, but keep distance.
  • f to follow the character closely.
  • Upper case letter moves backwards, like names has the First letter capitalized.
  • Lower case letter moves forward, like the rest of a name are written with lower case letters.

I don’t know if it helps of not, maybe… I just memorized them all.

All of them can be used with [count].

Examples

We love error handling, and don’t like _

We have this line and our cursor is on the S in StdEncoding.

encodedValue, _ := base64.StdEncoding.DecodeString(metadataValue)

We want to change the _ to err, a quick movement would be a F_, because that way we move backwards and the cursor will be placed on the target character. Now let’s change the _ character to err with c (change). c expect us to specify a motion, but we want to update only character with a longer text, l (basic vim movement with hjkl), so it’s cl.

Tidy up an error message

It can be very handy with other movement actions like “deleting up until”.

fmt.Errorf("bullshit fancy file error, happens sometimes: %w", err)

If the cursor is at the beginning of the line and we want to delete “bullshit” and “, happens sometimes”, because they shouldn’t be in the error at all:

First we move to the [b]ullshit with fb, now we can delete the first two words with d2f (there is a <space> after f). Now we have this:

fmt.Errorf("file error, happens sometimes: %w", err)

To remove the other part, we move to , placing the cursor on , so it’s f,, after that we delete everything up until :, but not :. Because we don’t want to delete : we can use t which stops before the target, our final magic combination will be dt: (delete to :). We are happy because we have our desired state.

fmt.Errorf("file error: %w", err)

The full sequence looks like this: fbd2f f,dt:. But that can be terrifying to see, so I left it to the end.

You can use them in macros easily, but that’s for a different day.