0

There are several points where I/O is passed through, some of which (to my knowledge) are the shell, pty, tty, termios, terminal emulator application. In most terminal emulators, long command lines (ones that exceed current $COLUMNS) are wrapped to a new line before the user submits the command by pressing Enter. Also, the line is wrapped backward to the line above when the appropriate number of characters are removed from the command line as one would expect.

My question is: where is this magic usually handled? Is it a termios setting, or part of the shell, or is the terminal emulator application responsible for this?

For more context, I'm using the Terminator terminal emulator application on Ubuntu - where the linewrapping works perfectly fine (so there should be no issues with my $PS1 prompt). But I'm working on my own terminal emulator application that works with a go pty spawner (github.com/kr/pty) and I'm having issues where long lines aren't wrapped to a new line, but the beginning of the same line.

5

In most terminal emulators, long command lines […] are wrapped to a new line before the user submits the command by pressing Enter.

This is not a function of the terminal emulator.

It is a function of your shell. Your shell is not a full-screen application, but it is doing cursor addressing.

When you are editing a command line in a shell, the line editing library in the shell is in full charge of how the line being edited is displayed. In the Bourne Again shell this is the GNU readline library. The Almquist shell uses libedit. Other shells, such as the Z Shell, have their own libraries.

These libraries are layered on top of the termcap/terminfo libraries, which record the terminal capabilities of your terminal emulator. Those capabilities include amongst other things the control sequences for positioning the cursor in relative or absolute terms, the sequences for clearing to the end of the line and the end of the screen, and whether or not your terminal has automatic margins.

With this and information about the width of the terminal determined from the TIOCGWINSZ ioctl (falling back to the COLUMNS variable for some libraries, or the termcap/terminfo database for others) in hand, the line editing library in the shell tracks the command line length and how many terminal lines it is displayed across. It intelligently moves the cursor around to repaint the input line as it is edited. Sometimes it might rely upon automatic margins, if your terminal has them. Sometimes it may explicitly reposition the cursor using control sequences.

The fact that it is doing this is what causes effects such as those discussed at https://superuser.com/questions/695338/ . One can mess up its idea of where the cursor is, and what cursor motions it needs to emit to write to a particular place on the screen, with incorrectly delimited control sequences in a prompt string.

Your terminal emulator does not deal in the notions of command lines, or line editing. It is not part of those layers. It sees a simple stream of characters and control sequences, which it must render. It is your terminal emulator's responsibility to implement the control sequences that are advertised for it in its termcap/terminfo entry. GNU readline, libedit, ZLE, vim, screen, and others will use what they find advertised. If you state in termcap/terminfo that your terminal has automatic margins, for example, then the emulator must do a line wrap when a character is printed at the right margin. If you state that your terminal can move the cursor up and down, then it must indeed do that when it receives the appropriate control sequences.

By the way: If GNU readline finds that it cannot move the cursor up, because the termcap/terminfo entry does not state a way to do so, one doesn't actually see line wrap at all. readline falls back to a mode where it sideways scrolls the input line, all on one line.

2

The terminal [emulator] is responsible for this. Moving to the first column of the next line is just what the terminal does after filling the last position on a line.

You can easily see that it isn't the shell doing this just by entering cat and typing some long lines. Shells like bash and zsh do in fact track the cursor position and the number of columns they believe the terminal has and output various terminal control sequences at the ends of lines but only so that they can implement some of their fancier line editing features (like right-hand prompts, horizontal scrolling, displaying and erasing tab completion menus, rewriting/refreshing the current line, etc...). The line wrapping would still happen if they didn't do that.

The tty layer may also have knowledge of the screen size but again, it's not used for ensuring that line wrap happens.

If your terminal doesn't do this, it's a bug in your terminal.

  • This isn't quite right. As JdeBP explains, shells designed for interactive use (bash, zsh, tcsh) take over wrapping to the next line. Most terminal do offer this feature, and wrapping does happen if the application lets it happen. A terminal doesn't have to do wrapping though: it can have infinite width if it wants. – Gilles Apr 14 '15 at 23:29
  • @Gilles Yes, bash and zsh do something special at end of line, but the point is that they don't need to in order for the wrapping to happen. The wrapping happens all by itself in the terminal. Still, I'll edit my answer a little bit. – Celada Apr 14 '15 at 23:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.