Introduction
Announcements

Schedule
Labs
Assignments
TA office hours

Tests, exam

Topic videos
Some course notes
Extra problems
Lecture recordings

Discussion board

Grades so far

Terminal control characters and stty

When you press the "backspace" or "delete" or "←" key on your keyboard, it sends a control character to that terminal window, and thence perhaps over ssh to a program running on teach.cs, etc.

What control character does it send, and how does the remote program know that this is meant as a "delete one character to the left" character?

Well, if you're reading this web page, chances are that the remote program DOESN'T know that this is meant as a delete-left key, and you're wanting to fix that.

To begin with, the ASCII character set uses positions 1 through 31 for what we call "control characters". ASCII character 1 is control-A, ASCII character 2 is control-B, and so forth. As a printable representation of these control characters, we usually write them as "^A", "^B", and so forth.

All of these control characters were prescribed meanings in the original ASCII standard. Some of these meanings were dubious. But some of them became widely used, such as the various control characters for newlines of various kinds, control-I for tab, and control-H for backspace ("BS").

The ASCII character set position 127 is called "DEL", for "delete". The distinction between BS and DEL has been interpreted variously over the decades, but most of the time, one of them means what you are trying to do when you press that "backspace" or "delete" or "←" key on your keyboard, and the other one doesn't mean anything, any more than any other control character.

In unix, by analogy to the naming of the first 26 control characters, given the position of the question mark in the ASCII character set it was decided to use "^?" as a printable representation of DEL (it makes sense if you look at the bit layout).

In unix, this "delete left" behaviour is known as "erase". The traditional terminal driver in unix can honour either one of these characters as the "erase" behaviour, but only one. The setting is controlled with a command named "stty" (for "set tty").

But we use the line-editing facilities of the traditional terminal driver less frequently these days. For example, most shells instead use "cbreak mode", in which every character can be received as input by the program separately, and then any backspacing, control-U to delete the line, etc, has to be implemented all over again by the shell. However, this then gives the shell the freedom to assign line-editing meaning to other control characters, and to the arrow keys. In this case, the shell invariably will accept either BS or DEL as "erase".

A different decision was taken by the authors of the "vi" program, which is older than the idea of the shell using cbreak mode. Although it puts the terminal into cbreak mode for the same reason, it actually CHECKS your stty setting, and honours it within vi's insert mode. If your erase character is set to BS, then BS will do "delete left" type behaviour but DEL will count as just another character (e.g. to be inserted, if you are in insert mode). If your erase character is set to DEL, the opposite applies.

So, if you are pressing the desired key for a "delete left" operation and instead you are seeing the control character, you can either change your terminal program's idea of which character to send when you press that key (there might be an option in "settings" or "preferences" somewhere), or you can change unix's idea of which control character is the erase character.

To change the erase character, both within vi and within any program which doesn't put the terminal into cbreak mode, type a command beginning with "stty erase", followed by the desired control character. The desired control character can be specified either by the control character itself, or by "^" and the appropriate letter or a question mark for DEL. Since your shell probably interprets control characters in cbreak mode, it might be easier to type the "^" version, although then you need to deal with the fact that "^" and "?" are both special characters to the shell hence should be quoted.

Note that if you are running vi, getting the undesired behaviour, press ^Z to get to the terminal, do the stty, and then "fg" to get back to vi, you will not fix the problem for that vi session! Vi checks only when you start it.

To make a "stty erase" command take effect in future logins and future terminal windows, you can put it in your .bash_login. You should not put stty commands in your .bashrc, because your .bashrc is run at times where there is no associated terminal (e.g. in expanding remote filename wildcards in an scp command), at which point the stty command would emit error messages. Your .bash_login is not run at such times.