public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>
Subject: Re: [PATCH v2] [gdb/tui] Fix superfluous newline for long prompt
Date: Fri, 14 Jul 2023 14:18:21 +0200	[thread overview]
Message-ID: <fadf580d-e28c-c3c8-0e34-be58cd6c20f7@suse.de> (raw)
In-Reply-To: <20230622191423.4197-1-tdevries@suse.de>

On 6/22/23 21:14, Tom de Vries via Gdb-patches wrote:
> 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.
> 

I'll commit this end of next week, unless there are comments.

Thanks,
- Tom

> Tested on x86_64-linux, no regressions.
> ---
>   gdb/testsuite/gdb.tui/long-prompt.exp | 18 +-----------------
>   gdb/tui/tui.c                         |  2 --
>   2 files changed, 1 insertion(+), 19 deletions(-)
> 
> diff --git a/gdb/testsuite/gdb.tui/long-prompt.exp b/gdb/testsuite/gdb.tui/long-prompt.exp
> index e4e8b75ede0..a08c08a884a 100644
> --- a/gdb/testsuite/gdb.tui/long-prompt.exp
> +++ b/gdb/testsuite/gdb.tui/long-prompt.exp
> @@ -101,29 +101,13 @@ with_test_prefix "prompt size == width" {
>       #   16 (gdb) set prompt 123456789A123456789B123
>       #   17 456789C123456789>
>       #   18 123456789A123456789B123456789C123456789>
> -    #   19
> -    #   20 123456789A123456789B123456789C123456789>
> -    #   21 set prompt (gdb)
> -    #   22 (gdb)
> -    #
> -    # Note that it would be nice to get instead:
> -    #
> -    #   16 (gdb) set prompt 123456789A123456789B123
> -    #   17 456789C123456789>
> -    #   18 123456789A123456789B123456789C123456789>
>       #   19 set prompt (gdb)
>       #   20 (gdb)
> -    #
> -    # The extra newline is added by rl_on_new_line_with_prompt, which decides
> -    # this as follows:
> -    #  /* 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. */
>   
>       gdb_assert { [Term::wait_for "^set prompt $gdb_prompt "] } \
>   	"got prompt back"
>   
> -    gdb_assert { $Term::_cur_row == 22 }
> +    gdb_assert { $Term::_cur_row == 20 }
>   }
>   
>   with_test_prefix "prompt size == width - 1" {
> diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c
> index 43be8161e4c..941c65c970f 100644
> --- a/gdb/tui/tui.c
> +++ b/gdb/tui/tui.c
> @@ -271,11 +271,9 @@ tui_rl_next_keymap (int notused1, int notused2)
>   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;
>   }
>   
> 
> base-commit: d4d5b571954a2bde2a14772d9b18027a9048eb2d


  reply	other threads:[~2023-07-14 12:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-22 19:14 Tom de Vries
2023-07-14 12:18 ` Tom de Vries [this message]
2023-07-21  7:37   ` Tom de Vries

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fadf580d-e28c-c3c8-0e34-be58cd6c20f7@suse.de \
    --to=tdevries@suse.de \
    --cc=gdb-patches@sourceware.org \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).