2024-01-12 23:30:44 +08:00
|
|
|
# Copyright 2023-2024 Free Software Foundation, Inc.
|
2023-06-09 06:12:59 +08:00
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
# Test a prompt one less than, equal to, and one more than screen width in
|
|
|
|
# TUI.
|
|
|
|
|
|
|
|
require allow_tui_tests
|
|
|
|
|
|
|
|
tuiterm_env
|
|
|
|
|
|
|
|
with_test_prefix "prompt size == width + 1" {
|
|
|
|
Term::clean_restart 24 40
|
|
|
|
|
|
|
|
if {![Term::enter_tui]} {
|
|
|
|
unsupported "TUI not supported"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
set prompt "123456789A123456789B123456789C123456789D>"
|
|
|
|
|
|
|
|
# Set new prompt, and set old prompt back.
|
|
|
|
send_gdb "set prompt $prompt\n"
|
|
|
|
send_gdb "set prompt (gdb) \n"
|
|
|
|
|
|
|
|
# Expected output:
|
|
|
|
#
|
|
|
|
# 16 (gdb) set prompt 123456789A123456789B123
|
|
|
|
# 17 456789C123456789D>
|
|
|
|
# 18 123456789A123456789B123456789C123456789D
|
|
|
|
# 19 >set prompt (gdb)
|
|
|
|
# 20 (gdb)
|
|
|
|
|
|
|
|
gdb_assert { [Term::wait_for "^>set prompt $gdb_prompt "] } \
|
|
|
|
"got prompt back"
|
|
|
|
|
|
|
|
gdb_assert { $Term::_cur_row == 20 }
|
|
|
|
}
|
|
|
|
|
|
|
|
with_test_prefix "prompt size == width + 1: end of screen" {
|
|
|
|
Term::clean_restart 24 40
|
|
|
|
|
|
|
|
if {![Term::enter_tui]} {
|
|
|
|
unsupported "TUI not supported"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
# Put prompt at last line.
|
2023-06-13 19:21:09 +08:00
|
|
|
Term::command "echo \\n\\n\\n\\n\\n\\n"
|
2023-06-09 06:12:59 +08:00
|
|
|
gdb_assert { $Term::_cur_row == 23 } "at last line"
|
|
|
|
|
|
|
|
set prompt "123456789A123456789B123456789C123456789D>"
|
|
|
|
|
|
|
|
# Set new prompt, and set old prompt back.
|
|
|
|
send_gdb "set prompt $prompt\n"
|
|
|
|
send_gdb "set prompt (gdb) \n"
|
|
|
|
|
|
|
|
# Expected output:
|
|
|
|
#
|
|
|
|
# 19 (gdb) set prompt 123456789A123456789B123
|
|
|
|
# 20 456789C123456789D>
|
|
|
|
# 21 123456789A123456789B123456789C123456789D
|
|
|
|
# 22 >set prompt (gdb)
|
|
|
|
# 23 (gdb)
|
|
|
|
|
|
|
|
gdb_assert { [Term::wait_for "^>set prompt $gdb_prompt "] } \
|
|
|
|
"got prompt back"
|
|
|
|
|
|
|
|
gdb_assert { $Term::_cur_row == 23 } "still at last line"
|
|
|
|
Term::check_region_contents "scrolling" 0 19 40 1 \
|
|
|
|
"^$gdb_prompt set prompt 123456789A123456789B123$"
|
|
|
|
}
|
|
|
|
|
|
|
|
with_test_prefix "prompt size == width" {
|
|
|
|
Term::clean_restart 24 40
|
|
|
|
|
|
|
|
if {![Term::enter_tui]} {
|
|
|
|
unsupported "TUI not supported"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
set prompt "123456789A123456789B123456789C123456789>"
|
|
|
|
|
|
|
|
# Set new prompt, and set old prompt back.
|
|
|
|
send_gdb "set prompt $prompt\n"
|
|
|
|
send_gdb "set prompt (gdb) \n"
|
|
|
|
|
|
|
|
# Expected output:
|
|
|
|
#
|
|
|
|
# 16 (gdb) set prompt 123456789A123456789B123
|
|
|
|
# 17 456789C123456789>
|
|
|
|
# 18 123456789A123456789B123456789C123456789>
|
|
|
|
# 19 set prompt (gdb)
|
|
|
|
# 20 (gdb)
|
|
|
|
|
|
|
|
gdb_assert { [Term::wait_for "^set prompt $gdb_prompt "] } \
|
|
|
|
"got prompt back"
|
|
|
|
|
[gdb/tui] Fix superfluous newline for long prompt
In test-case gdb.tui/long-prompt.exp, with a prompt of 40 chars, the same size
as the terminal width, we get a superfluous newline at line 19:
...
16 (gdb) set prompt 123456789A123456789B123
17 456789C123456789>
18 123456789A123456789B123456789C123456789>
19
20 123456789A123456789B123456789C123456789>
21 set prompt (gdb)
22 (gdb)
...
as well as a superfluous repetition of the prompt at line 20 once we type the
's' starting "set prompt".
I traced the superfluous newline back to readline's readline_internal_setup,
that does:
...
/* If we're not echoing, we still want to at least print a prompt, because
rl_redisplay will not do it for us. If the calling application has a
custom redisplay function, though, let that function handle it. */
if (_rl_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
...
else
{
if (rl_prompt && rl_already_prompted)
rl_on_new_line_with_prompt ();
else
rl_on_new_line ();
(*rl_redisplay_function) ();
...
and then we hit the case that calls rl_on_new_line_with_prompt, which does:
...
/* If the prompt length is a multiple of real_screenwidth, we don't know
whether the cursor is at the end of the last line, or already at the
beginning of the next line. Output a newline just to be safe. */
if (l > 0 && (l % real_screenwidth) == 0)
_rl_output_some_chars ("\n", 1);
...
This doesn't look like a readline bug, because the behaviour matches the
comment.
[ And the fact that the output of the newline doesn't happen in the scope of
tui_redisplay_readline means it doesn't get the prompt wrap detection
treatment, causing start_line to be incorrect, which causes the superfluous
repetition of the prompt. ]
I looked at ways to work around this, and managed by switching off
rl_already_prompted, which we set to 1 in tui_rl_startup_hook:
...
/* Readline hook to redisplay ourself the gdb prompt.
In the SingleKey mode, the prompt is not printed so that
the command window is cleaner. It will be displayed if
we temporarily leave the SingleKey mode. */
static int
tui_rl_startup_hook (void)
{
rl_already_prompted = 1;
if (tui_current_key_mode != TUI_COMMAND_MODE
&& !gdb_in_secondary_prompt_p (current_ui))
tui_set_key_mode (TUI_SINGLE_KEY_MODE);
tui_redisplay_readline ();
return 0;
}
...
Then I started looking at why rl_already_prompted is set to 1.
The use case for rl_already_prompted seems to be:
- app (application, the readline user) outputs prompt,
- app sets rl_already_prompted to 1, and
- app calls readline, which calls rl_on_new_line_with_prompt, which figures
out how long the prompt is, and sets a few readline variables accordingly,
which can be used in the following call to rl_redisplay_function.
AFAICT, TUI does not fit this pattern. It does not output an initial prompt,
rather it writes the prompt in every rl_redisplay_function. It doesn't use
the variables set by rl_on_new_line_with_prompt, instead it figures stuff out
by itself.
Fix this by removing the rl_already_prompted setting.
Also remove the call to tui_redisplay_readline, it's not necessary, the
function is called anyway.
Tested on x86_64-linux, no regressions.
2023-07-21 14:17:51 +08:00
|
|
|
gdb_assert { $Term::_cur_row == 20 }
|
2023-06-09 06:12:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
with_test_prefix "prompt size == width - 1" {
|
|
|
|
Term::clean_restart 24 40
|
|
|
|
|
|
|
|
if {![Term::enter_tui]} {
|
|
|
|
unsupported "TUI not supported"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
set prompt "123456789A123456789B123456789C12345678>"
|
|
|
|
|
|
|
|
# Set new prompt, and set old prompt back.
|
|
|
|
send_gdb "set prompt $prompt\n"
|
|
|
|
send_gdb "set prompt (gdb) \n"
|
|
|
|
|
|
|
|
# Expected output:
|
|
|
|
#
|
|
|
|
# 16 (gdb) set prompt 123456789A123456789B123
|
|
|
|
# 17 456789C12345678>
|
|
|
|
# 18 123456789A123456789B123456789C12345678>s
|
|
|
|
# 19 et prompt (gdb)
|
|
|
|
# 20 (gdb)
|
|
|
|
|
|
|
|
gdb_assert { [Term::wait_for "^et prompt $gdb_prompt "] } \
|
|
|
|
"got prompt back"
|
|
|
|
|
|
|
|
gdb_assert { $Term::_cur_row == 20 }
|
|
|
|
}
|