How to change the cursor theme in CLI?

The cursor is drawn by the terminal or terminal emulator, not the applications running within them. Some of them have provision to allow the user to change the shape or attributes of the cursor using escape sequences.

Changing the cursor shape independently from the type of the terminal can be done using the cnorm (normal cursor), civis (cursor invisible), or cvvis (cursor very visible) terminfo capabilities (for instance using the tput command). However, it doesn't give you any warranty that any of cnorm or cvvis will be a block cursor.

To affect the blinkiness, shape and colour and behaviour of the cursor specifically, that will have to be done on a per-terminal basis.

On Linux on x86 PCs VGA and frame buffer virtual consoles, it can be controlled using escape sequences like:

printf '\e[?x;y;zc'

In the simplest form:

printf '\e[?xc'

You define the height of the cursor where x ranges from 1 (invisible cursor) to 8 (full block), 0 giving you the default (currently, same as 2).

So:

printf '\e[?8c'

will give you a full block cursor.

Actually that's what tput cvvis sends (while tput cnorm sends \e[0c and civis \e[1c).

When using the 3 parameter form, the behaviour will vary with the underlying video driver. For instance to get a sort of grey non-blinking block cursor as your question suggests, you'd do:

printf '\e[?81;128;240c'

In a PC VGA Linux console. And:

printf '\e[?17;30;254c'

In a frame buffer Linux console.

Now, that was Linux specific, other terminals have different ways to change the cursor shape. For instance xterm and rxvt and their derivatives use the same sequences as the VT520 terminal to set the cursor shape:

printf '\e[x q'

Where x takes a value from 1 to 6 (from xterm manual):

  • 0 -> blinking block.
  • 1 -> blinking block (default).
  • 2 -> steady block.
  • 3 -> blinking underline.
  • 4 -> steady underline.
  • 5 -> blinking bar (xterm).
  • 6 -> steady bar (xterm).

And the colour can be set with:

printf '\e]12;%s\a' 'colour'

So your grey steady block cursor could be achieved there with:

printf '\e[2 q\e]12;grey\a'

For most X11 terminal emulators, you can also change the cursor attributes via command-line options to the command that starts the emulator or via config files or X11 resources, or menus.

For instance, for xterm, you have the -uc/+uc option for underline cursor, -ms for its colour, and cursorBlink, cursorColor, cursorOffTime, cursorOnTime, cursorUnderLine, alwaysHighlight resources to configure it.

And the default menu on Ctrl + left click has an option to turn blinking on or off.


As of today, the current version of agetty (contained in util-linux 2.27.1 [util-linux is the linux package providing most core commands, like login, su, mount, more, kill - to name a few] - and you should have it if your linux kernel version is >=4.4) has a different behavior than described in the yet-to-be-updated kernel.org documentation (Software cursor for VGA).

Consider

echo -n -e '\e[?byte1;byte2;byte3c'

byte1:

+---------------+---------------+
|  high nibble  |   low nibble  |
+---+-----------+-----------+---+
|msb|           |           |lsb|
+---+---+---+---+---+---+---+---+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---+---+---+---+---+---+---+---+
                  |   |   |   |
                  |   |   |   +-+
                  |   |   |     |   These bits specify the 8
                  |   |   +-----+-> possible  blinking HW caret
                  |   |         |   
                  |   +---------+
                  |
                  +---------------> When set, this bit enables SW
                                    caret instead of HW caret

byte2 (SW caret):

                +-----------------> A pretty useless mask applied
                |                   to bits in byte3
+---------------+---------------+
|  high nibble  |   low nibble  |
+---+-----------+-----------+---+
|msb|           |           |lsb|
+---+---+---+---+---+---+---+---+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---+---+---+---+---+---+---+---+

byte3 (SW caret):

+---------------+---------------+
|  high nibble  |   low nibble  |
+---+-----------+-----------+---+
|msb|           |           |lsb|
+---+---+---+---+---+---+---+---+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---+---+---+---+---+---+---+---+
  |   |   |   |
  |   |   |   +-------------------> Highlighting
  |   |   |
  |   |   +---------------------+
  |   |                         |
  |   +-------------------------+-> Color
  |                             |
  +-----------------------------+

Highlighting: highligths the character beneath the caret (e.g. changing it to white [true shiny white] instead of dark white [the light gray that is commonly the default for TTYs]).

Color: the color of the caret. Note that, compared to the usual order of ANSI color codes we all know and love, bits are reversed, so -for this triplet- the 7th is the lsb while the 5th is the msb.

So, while in the 70s ANSI defined the following color codes, setting a de-facto standard adopted universally for TTYs, miscellaneous linux terminals, consoles, and whatnot

0 black
1 red
2 green
3 yellow or dark yellow
4 blue or dark blue
5 magenta, purple or violet
6 cyan or light blue
7 white or dark white (light gray)

in this case we have the opposite

7 white or dark white (light gray)
6 cyan or light blue
5 magenta, purple or violet
etc.

So, here comes the list:

#Hardware carets (blinking and [dark ]white)
echo -n -e '\e[?0c' #default caret
echo -n -e '\e[?1c' #invisible caret
echo -n -e '\e[?2c' #underscore caret
echo -n -e '\e[?3c' #thicker underscore caret
echo -n -e '\e[?4c' #smaller block caret
echo -n -e '\e[?5c' #small block caret
echo -n -e '\e[?6c' #big block caret
echo -n -e '\e[?7c' #biggest block caret
#On my Linux machine, both 6 and 7 are the big rectangular full-size block caret

#Software carets (non-blinking and colored)
echo -n -e '\e[?16;0;0c'  #00001000 0 00000000 black (thus invisible on black background)
echo -n -e '\e[?16;0;128c'#00001000 0 10000000 red
echo -n -e '\e[?16;0;64c' #00001000 0 01000000 green
echo -n -e '\e[?16;0;192c'#00001000 0 11000000 yellow
echo -n -e '\e[?16;0;32c' #00001000 0 00100000 blue
echo -n -e '\e[?16;0;160c'#00001000 0 10100000 magenta
echo -n -e '\e[?16;0;96c' #00001000 0 01100000 cyan
echo -n -e '\e[?16;0;224c'#00001000 0 11100000 dim white
echo -n -e '\e[?16;0;16c' #00001000 0 00010000 black     + highlighting
echo -n -e '\e[?16;0;144c'#00001000 0 10010000 red       + highlighting
echo -n -e '\e[?16;0;80c' #00001000 0 01010000 green     + highlighting
echo -n -e '\e[?16;0;208c'#00001000 0 11010000 yellow    + highlighting
echo -n -e '\e[?16;0;48c' #00001000 0 00110000 blue      + highlighting
echo -n -e '\e[?16;0;176c'#00001000 0 10110000 magenta   + highlighting
echo -n -e '\e[?16;0;112c'#00001000 0 01110000 cyan      + highlighting
echo -n -e '\e[?16;0;240c'#00001000 0 11110000 dim white + highlighting

Tags:

Terminal