Amy Grinn UP | HOME Fedi

I have strong opinions on the shape of your cursor

I only have to look at it for hours every day.

Inserting text

A text file can be visualized as a grid starting from the top left and going to the bottom right. When inserting text, you operate on individual cells in the grid. Whenever a key is pressed, a cell is replaced by the key and the existing cell contents, along with all others further to the right on this line, get shifted one cell to the right. But which cell, exactly, is replaced by the key you press? That is defined by the cursor.

Have you ever tried to click in between letters in order to get your cursor to go in the right place? I have, because the default cursor for most text editors is a vertical bar. I probably won't shatter any minds with this statement, but: it's impossible to click on a target without any width. The vertical bar gives an illusion that there is a pixel-wide gutter between each character. Conceptually though, the cursor exists at the location of the cell to the right of the vertical bar. This is the cell that is replaced by pressing a key, and who's contents are shifted to the right along with other cells further to the right.

The correct shape for inserting text is a box or a horizontal bar.

(setq-default cursor-type 'box)
;; (setq-default cursor-type 'hbar)

This will train you to click on (or otherwise navigate to) the letter you want to replace rather than the non-existent gutter between characters. Moreover, have you ever wondered why the delete key isn't called 'forwardspace'? With a vertical bar, it seemed to do just the opposite of backspace. Now, it finally makes sense, as it just deletes the cell the cursor is under.

Modal editing

If you haven't heard of modal editing before, it means that you switch between insert and command mode often whenever editing a text file. Insert mode is for writing brand new text while command mode is typically used to copy, arrange, and trim existing text. Instead of inserting letters into the text, in command mode each key is bound to some such action. Anybody who has used a keyboard has used insert mode probably most of their life. If you find yourself formatting badly copy-and-pasted text a lot or trying to select words and sentences using your mouse (blech), you may want to try out modal editing. A lot of text editors have plugins for this and vim has it by default.

Modal editing can be dangerous though, because command mode is so powerful yet the rate you usually type in insert mode is so fast. I typically write in full sentences and sometimes halfway through I'll realize I'm not in insert mode, typed 20 commands, and have no idea what they each did. One way to warn yourself that you are in command mode is by changing the shape of the cursor.

Text-editing commands are not done on cells but on rectangles. Rectangles, within the grid conception of a text file, are defined by two sets of boundary coordinates: the top left corner and the bottom right corner. A lot of commands are for rectangles on a single line, with a height of just 1. For example, most modal editing software has a command to select a single word. This is typically represented by the word higlighted in a different color and the cursor placed on the character to the right of the selection. The cell where the cursor ends up is not part of the selection, it simply defines the rightmost boundary coordinate for the rectangle.

For modal editing, the correct shape of the cursor in command mode is a vertical bar. There doesn't seem to be an agreed upon default, so this should be it. A lot of commands start and include the cursor position, move to the right, and operate on everything in between, excluding the final cursor position. The vertical bar makes this seemingly complicated convention completely mindless: just trap the text between the walls of the cursor. One wall goes where your cursor is, one wall goes where it will end up, and everything in between will be operated on.

This configuration will be different for each modal editing plugin. Right now, I'm using my fork of objed, which has this behavior built in.

Here is a config for boon-mode:

(setq boon-default-cursor-type 'box
      boon-insert-cursor-type 'box
      boon-command-cursor-type 'bar)

Here is a config for god-mode:

(defun my-god-mode-update-cursor ()
  (setq cursor-type (if (or god-local-mode buffer-read-only)
                        'bar
                        'box)))

(add-hook 'god-mode-enabled-hook #'my-god-mode-update-cursor)
(add-hook 'god-mode-disabled-hook #'my-god-mode-update-cursor)

Created: 2022-04-19

Last modified: 2025-01-28