readline
readline copied to clipboard
Readline unnecessarily redraws the last line in the terminal
At CockroachDB we are now using expect to test the SQL shell and this shows all the characters sent by the program to the terminal. In our expect traces we see things like this:
send: sending "select 1;\r" to { exp6 }
expect: does ":26257> \u0008" (spawn_id exp6) match glob pattern "1 row"? no
root@:26257> se
expect: does ":26257> \u0008\u001b[J\u001b[2K\rroot@:26257> s\u001b[J\u001b[2K\rroot@:26257> se" (spawn_id exp6) match glob pattern "1 row"? no root@:26257> selec
expect: does ":26257> \u0008\u001b[J\u001b[2K\rroot@:26257> s\u001b[J\u001b[2K\rroot@:26257> se\u001b[J\u001b[2K\rroot@:26257> sel\u001b[J\u001b[2K\rroot@:26257> sele\u001b[J\u001b[2K\rroot@:26257> selec" (spawn_id exp6) match glob pattern "1 row"? no
root@:26257> select 1;
expect: does ":26257> \u0008\u001b[J\u001b[2K\rroot@:26257> s\u001b[J\u001b[2K\rroot@:26257> se\u001b[J\u001b[2K\rroot@:26257> sel\u001b[J\u001b[2K\rroot@:26257> sele\u001b[J\u001b[2K\rroot@:26257> selec\u001b[J\u001b[2K\rroot@:26257> select\u001b[J\u001b[2K\rroot@:26257> select \u001b[J\u001b[2K\rroot@:26257> select 1\u001b[J\u001b[2K\rro
ot@:26257> select 1;" (spawn_id exp6) match glob pattern "1 row"? no
root@:26257> select 1;
What is happening here, is that after every character typed by the user (received by readline from the terminal), readline issues \033[J\033[2K\r to the terminal then redraws (re-outputs) the prompt and all the characters typed so far.
This is sub-optimal: a redraw should only be necessary when characters previously present in the readline buffer are modified (e.g. when using left-arrow, up-arrow etc). During normal input of non-special characters, this redraw is unnecessary.
Also on slow terminals (like over slow ssh connections) this redraw becomes clearly noticeable to the user for very long inputs.
I can see some usefulness while doing line redraw such as highlighting:
but the flickering can be somewhat annoying.
@chzyer
Before I knew this project I wrote a similar one that had the same issue which I solved by:
\r*%s*\033[K (%s being the content or prompt + content)
unlike \033[2K which deletes entire line, I simple move cursor back '\r', overwrite the content and finally \033[K deleting the rest of the line, no more input flickering
although I'm not sure about \033[K support across the terminals