The related posting Mac OS X terminal and GNU screen scrollback essentially advises you to suppress switching to the alternate screen of xterm. While in the alternate screen, you would not necessarily be able to use the scroll-wheel to see xterm's scrollback. A program running in xterm
would only see the escape sequences if it enables the xterm mouse protocol.
By default, screen
does not do this. It does have a setting which enables the mouse protocol, called mousetrack
:
This command determines whether screen
will watch for mouse clicks.
When this command is enabled, regions that have been split in various
ways can be selected by pointing to them with a mouse and left-
clicking them. Without specifying on or off, the current state is
displayed. The default state is determined by the "defmousetrack"
command.
But
Instead (see the first couple of links), some users have altered the xterm configuration to send screen-commands as the result of the scrolling wheel. A drawback to doing that is that it works only for the combination of xterm+screen.
Linux, Bash.
Bash uses stderr (file descriptor 2
) to print its command prompt and command line. Use tmux
to display two shells one above the other (or just place two GUI windows, terminal emulators one above the other). In the lower one invoke tty
. Don't use the lower shell directly from now on. In the upper one redirect file descriptor 1
to the tty of the lower one (e.g. exec 1>/dev/pts/2
).
Ctrl+L clears the upper, clear
clears the lower. Each portion is multi-line. Thanks to tmux
's features you can resize them (i.e. move the border up and down).
Use this to make commands appear also in the lower portion of the display:
trap 'printf "%s\n" "-----$ $BASH_COMMAND"' DEBUG
I tested the solution and at some point my terminal window looked like this:
kamil@foo:~$ ls -l /proc/$$/fd
kamil@foo:~$ uname -r
kamil@foo:~$ cat /etc/issue
kamil@foo:~$ █
──────────────────────────────────────────────────────────────────────
-----$ ls --color=auto -l /proc/$$/fd
total 0
lrwx------ 1 kamil kamil 64 Sep 9 20:42 0 -> /dev/pts/3
l-wx------ 1 kamil kamil 64 Sep 9 20:42 1 -> /dev/pts/2
lrwx------ 1 kamil kamil 64 Sep 9 20:42 2 -> /dev/pts/3
lrwx------ 1 kamil kamil 64 Sep 9 21:13 255 -> /dev/pts/3
-----$ uname -r
4.15.0-33-generic
-----$ cat /etc/issue
Ubuntu 18.04.1 LTS \n \l
(Note: --color=auto
appeared because my ls
is an alias).
Expect interactive tools (like text editors) to misbehave, so it's better to revert the change while calling them. Example:
1>&2 nano
Some shells (e.g. zsh
) use a separate file descriptor 10
for command line. This allows you to redirect stderr to the lower (or yet another, 3rd) tty, keeping the command line in the upper one.
Best Answer
Analysis
You call the behavior "weird" but it's by design.
clear
does not move text out of the screen, it actually clears what's on the screen. Strictly it only tells the terminal (terminal emulator) to do it.In some terminals
clear
effectively clears the entire scrollback buffer. At leastclear
in my Kubuntu does it; with-x
I can ask it not to. Seeman 1 clear
.My
$TERM
isxterm-256color
and this is howclear
works for me:clear -x
is equivalent toprintf '\033[H\033[2J'
,sole
clear
is equivalent toprintf '\033[H\033[2J\033[3J'
.These sequences are ANSI escape codes. The terminal is supposed to interpret them.
CSI n ; m H
n
, columnm
. […]CSI n J
Note what
clear
prints strongly depends on$TERM
. E.g. if I pick a "random" terminal:The above
clear
does not use ED; it uses CNL:CSI n E
n
(default1
) lines down. […]which does not clear the screen in my terminal. Maybe it does in a real
ztx
; or it doesn't, I don't know. Anywayclear
"thinks" the terminal isztx
and forztx
CNL is the best choice.In any case we could build and use an equivalent
printf
command. The very point ofclear
is it checks$TERM
in the environment and then looks in the terminfo database (seeman 5 terminfo
) to determine how to clear the screen. Withprintf
we would need to do this manually.It's not impossible some implementation(s) of
clear
in some circumstances (i.e. for some value of$TERM
) print a sequence that does what you want.And then there is the terminal (terminal emulator). Even if
clear
prints\033[2J
, the terminal may react by doing what you want. Maybe there is an option that lets you choose. You can write a terminal emulator that reacts this way.I often use tmux, it implements its own scrollback buffer. Inside it
$TERM
expands toscreen
;clear
andclear -x
are both equivalent toprintf '\033[H\033[J'
. This sequence does what you want when interpreted by tmux. But outside of tmux (in my case with scrollback buffer provided by Konsole) the same sequence replicates your problem. I deduce tmux is a terminal emulator that reacts the way you want.My point is:
clear
prints different things, depending on what it "thinks" your terminal is; then the terminal interprets these things and it may react in whatever way. E.g. yourclear
seems to do what myclear -x
does: it does not clear the entire scrollback buffer, only the visible part. So maybe yourclear
does not print\033[3J
; or maybe it does but your terminal does not clear the buffer fully anyway.Maybe you could find a different value of
$TERM
so yourclear
consulting your terminfo database will be able to make your terminal emulator do what you want. Even if you could do this, I wouldn't say it's the Right Thing in general. Changing$TERM
can break other things.Solution 1: tmux
Use tmux and its scrollback buffer. My tests indicate it behaves the way you want (at least when
clear
sees$TERM
asscreen
). The tool is a terminal multiplexer, I use it routinely because of its other features and I had to explicitly get out of it to write some parts of this answer.It may be a major change in how you work in terminals. In my opinion it's worth it. Note using the scrollback buffer of tmux is in many aspects different than using the scrollback buffer of a terminal emulator.
Consider at least trying tmux.
Solution 2: custom
clear
as a shell functionIt seems you don't want to clear anything; you want to move text out of the screen and place the prompt at the top. So let's do this:
The function overrides the
clear
command when invoked without arguments; it falls back to the command otherwise. When it overrides, the function prints just the right number of newlines to move the previous content out of the screen; then regularclear -x
is invoked to clear the newlines and place the prompt at the top.Notes:
tput lines
is not portable. If there is any problem with this command then the function will only callcommand clear -x
.command clear -x
assumes yourclear
executable supports-x
like mine does. Judging by the question you don't need-x
, your soleclear
does not clear the entire buffer (maybe because yourclear
is different; maybe because your terminal(s) are different). It may be enough to callprintf '\033[H\033[2J'
instead. On the other handcommand clear …
consults the terminfo database, it's a feature one may want from the function as well. Adjust the function to your needs.clear
, not during.~/.bashrc
in case you use Bash outside of tmux, and still the things should work fine when you use Bash inside tmux.clear
regardless of the shell.