7

In Ubuntu/gnome-terminal, if I run:

$ stty -icrnl

Then launch the GHC interactive environment (a Haskell console):

$ ghci

Then pressing Return does not submit the line; however, Enter does.

However, with:

$ stty icrnl

Both Return and Enter submit the line.

I don't really understand the behaviour; surely Return will be submitting the newline character in both cases?

2 Answers 2

12

The first step in understanding what's going on is to be aware that there are in fact two “newline” characters. There's carriage return (CR, Ctrl+M) and line feed (LF, Ctrl+J). On a teletype, CR moves the printer head to the beginning of the line while LF moves the paper down by one line. For user input, there's only one relevant concept, which is “the user has finished entering a line”, but unfortunately there's been some divergence: Unix systems, as well as the very popular C language, use line feed to represent line breaks; but terminals send a carriage return when the user presses the Return or Enter key.

The icrnl setting tells the terminal driver in the kernel to convert the CR character to LF on input. This way, applications only need to worry about one newline character; the same newline character that ends lines in files also ends lines of user input on the terminal, so the application doesn't need to have a special case for that.

By default, ghci, or rather the haskeline library that it uses, has a key binding for Ctrl+J, i.e. LF, to stop accumulating input and start processing it. It has no binding for Ctrl+M i.e. CR. So if the terminal isn't converting CR to LF, ghci doesn't know what to do with that character.

Haskeline instructs the terminal to report keypad keys with escape sequences. It queries the terminal's terminfo settings to know what those escape sequences are (kent entry in the terminfo database). (The terminfo database is also how it knows how to enable keypad escapes: it sends the smkx escape sequence, and it sends rmkx on exit to restore the default keypad character mode.) When you press the Enter key on the keypad in ghci, that sends the escape sequence \eOM, which haskeline recognizes as a binding to stop accumulating input and start processing it.

2
  • Experimenting with this just now I found that the behavior of Return and Enter always sends 0x0a (LF). But depending on the settings for icrnl or inlcr you many influence the mapping for Ctrl-J and Ctrl-M. Is there a way to change the behavior of the Return and Enter keys?
    – sherrellbc
    Commented May 16, 2022 at 16:07
  • @sherrellbc It depends on your terminal emulator. Commented May 16, 2022 at 17:39
6

Referring to both Return and Enter sounds as if you are describing the keys respectively on the main part of the keyboard and on the numeric keypad often on the right-side of the main part:

enter image description here

However, only the first of those corresponds to the key which (unmodified) sends controlM. The key on the numeric keypad may send a carriage return or whatever, but may actually send an escape sequence, e.g., escapeOM, for VT100-like terminals.

You can see the different key values by echoing them, e.g., using cat -v.

3
  • I find that xterm sends \eOM only after a tput smkx and without num-lock. I'd doubt a tty line discipline would treat \eOM (and not \r) as accept-line though, so I'd find it unlikely to explain the behaviour shown by the OP Commented Jan 4, 2016 at 23:36
  • OP is referring to behavior within ghci, which could modify the keypad-setting. Commented Jan 4, 2016 at 23:42
  • 1
    Indeed, ghci does seem to have its own line editor that honours \eOM as accept-line. It does change the line discipline (to leave icanon at least), but does not touch icrnl. So it does explain the OP's problem indeed. Commented Jan 4, 2016 at 23:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .