From patchwork Wed Apr 19 13:37:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 68001 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7C6903857711 for ; Wed, 19 Apr 2023 13:38:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7C6903857711 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1681911506; bh=V0+OUEumdQFxZr4gXTXwNFH+NnDt3fTFWmHlWnrjry0=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=M9U8wqEDJJHFN/iHjFAtakiMxuO1K/Cb6/RGMkcxr3lJ1FxgktxJIf346O3oaIso5 sJ/YbZ8IhmcEMvc981nyk0gOQVkhhaylNHZvywCxThDESHSCxlF3qQPNtAhVpIu8wi 5MPTOo7BILFPTKFVtc5N4pYoqSDpR4Thdv763OZo= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by sourceware.org (Postfix) with ESMTPS id 703D73858C00 for ; Wed, 19 Apr 2023 13:37:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 703D73858C00 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 83B3B21979; Wed, 19 Apr 2023 13:37:40 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 68FB813580; Wed, 19 Apr 2023 13:37:40 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 7FcvGKTuP2Q0MgAAMHmgww (envelope-from ); Wed, 19 Apr 2023 13:37:40 +0000 To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [RFC] [gdb/tui] Add set tui border-kind acs-or-space/acs-or-ascii Date: Wed, 19 Apr 2023 15:37:43 +0200 Message-Id: <20230419133743.3288-1-tdevries@suse.de> X-Mailer: git-send-email 2.35.3 MIME-Version: 1.0 X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Tom de Vries via Gdb-patches From: Tom de Vries Reply-To: Tom de Vries Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" The gdb TUI testsuite uses a custom ansi terminal emulator (tuiterm.exp) in order to be able to inspect the state of the terminal, and consequently runs all test-cases using TERM=ansi. Once in a while I manually replay a test-case on an actual terminal emulator, using TERM=ansi to make sure I trigger the same behaviour, and run into funny looking borders, like this: ... ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ [ No Source Available ] ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ... This is PR tui/30370. AFAICT, otherwise everything works as expected. Negative effects though may include: - a user assessing that "something" went wrong, and not knowing the scope of the problem abandoning the TUI session, and - a GDB developer spending time debugging TUI to understand what went wrong. The problem can be worked around in GDB, by using a different "tui border-kind" than acs, say ascii, such that we have: ... +-----------------------------+ | | | [ No Source Available ] | | | +-----------------------------+ ... The problem is known in the context of ncurses [1], and a workaround can be applied by setting the environment variable NCURSES_NO_UTF8_ACS to 1, which gives us the desired: ... ┌─────────────────────────────┐ │ │ │ [ No Source Available ] │ │ │ └─────────────────────────────┘ ... [ Note that the workaround is applied automatically by ncurses for TERM=screen and TERM=linux. ] But, you have to know about these workarounds in order to be able to apply them. It would be nice if gdb could detect when a workaround is required, and apply the ncurses one without the user even having to be aware of it. But AFAIU that's not possible (and arguably, if that were the case, the logic would have been applied in ncurses). Another option is to detect if a workaround may be required, inform the user about the workaround(s), and ask the user if gdb should apply one of the workarounds if possible, but that's a bit intrusive. Instead, introduce two new tui border-kind values acs-or-space and acs-or-ascii, and change the default from acs to acs-or-ascii. For value acs-or-ascii, if gdb detects a workaround may be required, it uses ascii, and otherwise acs. More concretely, this means the border kind is now ascii by default (for my default environment with TERM=xterm and NCURSES_NO_UTF8_ACS unset) while "show tui border-kind" mentions the reason the fallback is chosen: ... $ gdb -q -batch -ex "show tui border-kind" The kind of border for TUI windows is "acs-or-ascii" \ (ascii, NCURSES_NO_UTF8_ACS unset). ... [ Note that we could extend the reason to: ... (ascii, TERM != screen && TERM != linux && NCURSES_NO_UTF8_ACS unset) ... or ... (ascii, TERM = xterm && NCURSES_NO_UTF8_ACS unset) ... but I'm not sure if this would make things more clear. ] And if we tell GDB that the workaround is or isn't necessary by setting NCURSES_NO_UTF8_ACS, we get acs: ... $ NCURSES_NO_UTF8_ACS=1 gdb -q -batch -ex "show tui border-kind" The kind of border for TUI windows is "acs-or-ascii" (acs). $ NCURSES_NO_UTF8_ACS=0 gdb -q -batch -ex "show tui border-kind" The kind of border for TUI windows is "acs-or-ascii" (acs). ... Or likewise, if we use TERM=screen or TERM=linux: ... $ TERM=screen gdb -q -batch -ex "show tui border-kind" The kind of border for TUI windows is "acs-or-ascii" (acs). $ TERM=linux gdb -q -batch -ex "show tui border-kind" The kind of border for TUI windows is "acs-or-ascii" (acs). ... RFC for now, so: - no docs, - no attempt to make things efficient. Is this approach a good idea? Any other comments? Tested on x86_64-linux. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30370 [1] https://invisible-island.net/ncurses/man/ncurses.3x.html#h3-NCURSES_NO_UTF8_ACS --- gdb/testsuite/gdb.tui/tui-border-kind.exp | 83 +++++++++++++++++++++ gdb/testsuite/lib/tuiterm.exp | 4 + gdb/tui/tui-win.c | 91 ++++++++++++++++++++--- 3 files changed, 167 insertions(+), 11 deletions(-) create mode 100644 gdb/testsuite/gdb.tui/tui-border-kind.exp base-commit: 28ab94f51dcdee056d96e57ad04c27c22cf854ea diff --git a/gdb/testsuite/gdb.tui/tui-border-kind.exp b/gdb/testsuite/gdb.tui/tui-border-kind.exp new file mode 100644 index 00000000000..cd6bf0899f0 --- /dev/null +++ b/gdb/testsuite/gdb.tui/tui-border-kind.exp @@ -0,0 +1,83 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . + +# Check that tui border-kind acs-or-ascii results in the right tui +# border-kind. + +# We set variables in env on build that we need on host, so we require +# host == build. +require {!is_remote host} + +# Don't use tuiterm_env, it just supports tui border-kind ascii. +# So we do a more basic test, and don't enter TUI. + +with_test_prefix TERM=screen { + save_vars { env(TERM) } { + setenv TERM screen + clean_restart + + # Check that TERM=screen selects acs. + gdb_test "show tui border-kind" \ + {The kind of border for TUI windows is "acs-or-ascii" \(acs\).} + + } +} + +with_test_prefix TERM=linux { + save_vars { env(TERM) } { + setenv TERM linux + clean_restart + + # Check that TERM=linux selects acs. + gdb_test "show tui border-kind" \ + {The kind of border for TUI windows is "acs-or-ascii" \(acs\).} + } +} + + +with_test_prefix TERM=ansi { + save_vars { env(TERM) } { + setenv TERM ansi + + with_test_prefix NCURSES_NO_UTF8_ACS=1 { + setenv NCURSES_NO_UTF8_ACS 1 + clean_restart + + # Check that TERM=linux and NCURSES_NO_UTF8_ACS=1 selects acs. + gdb_test "show tui border-kind" \ + {The kind of border for TUI windows is "acs-or-ascii" \(acs\).} + } + + with_test_prefix NCURSES_NO_UTF8_ACS=0 { + setenv NCURSES_NO_UTF8_ACS 0 + clean_restart + + # Check that TERM=linux and NCURSES_NO_UTF8_ACS=0 selects acs. + gdb_test "show tui border-kind" \ + {The kind of border for TUI windows is "acs-or-ascii" \(acs\).} + } + + with_test_prefix NCURSES_NO_UTF8_ACS=unset { + unset -nocomplain env(NCURSES_NO_UTF8_ACS) + clean_restart + + # Check that TERM=ansi with NCURSES_NO_UTF8_ACS unset selects ascii. + gdb_test "show tui border-kind" \ + [concat \ + {The kind of border for TUI windows is "acs-or-ascii"} \ + {\(ascii, NCURSES_NO_UTF8_ACS unset\).}] + } + } +} diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp index 05edfe9a5b1..3d7a9df52de 100644 --- a/gdb/testsuite/lib/tuiterm.exp +++ b/gdb/testsuite/lib/tuiterm.exp @@ -804,7 +804,11 @@ namespace eval Term { return 0 } + # We could drop this, and the default tui border-kind acs-or-ascii + # would normally pick ascii. But we'd run into if NCURSES_NO_UTF8_ACS + # would be set, which would pick acs instead. gdb_test_no_output "set tui border-kind ascii" + gdb_test_no_output "maint set tui-resize-message on" return 1 } diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c index 3b17cb8dd29..1339fc0c8e2 100644 --- a/gdb/tui/tui-win.c +++ b/gdb/tui/tui-win.c @@ -93,6 +93,8 @@ static const char *const tui_border_kind_enums[] = { "space", "ascii", "acs", + "acs-or-space", + "acs-or-ascii", NULL }; @@ -207,15 +209,80 @@ The attribute mode to use for the TUI window borders is \"%s\".\n"), value); } -static const char *tui_border_kind = "acs"; +/* Actual value of "tui border-kind" setting. X-or-y values allowed. */ +static const char *tui_border_kind_setting = "acs-or-ascii"; + +/* Actual value of "tui border-kind". X-or-y values not allowed. */ +static const char *tui_border_kind_value = nullptr; + +/* Reason why y was used in a X-or-y value for "tui border-kind". */ +static const char *tui_border_kind_value_reason = nullptr; + +static void +determine_tui_border_kind_value (void) +{ + const char *fallback = nullptr; + + tui_border_kind_value_reason = ""; + + if (strcmp (tui_border_kind_setting, "acs-or-ascii") == 0) + { + /* Tentatively set to acs, and define fallback. */ + tui_border_kind_value = "acs"; + fallback = "ascii"; + } + else if (strcmp (tui_border_kind_setting, "acs-or-space") == 0) + { + /* Tentatively set to acs, and define fallback. */ + tui_border_kind_value = "acs"; + fallback = "space"; + } + else + { + tui_border_kind_value = tui_border_kind_setting; + return; + } + + char *env_term = getenv ("TERM"); + if (strcmp (env_term, "linux") == 0 || strcmp (env_term, "screen") == 0) + { + /* Ncurses knows how to handle these TERM values. */ + return; + } + + char *env_ncurses_no_utf8_acs = getenv ("NCURSES_NO_UTF8_ACS"); + if (env_ncurses_no_utf8_acs != nullptr) + { + /* The user knowns if the workaround is required or not. */ + return; + } + + /* There may be problems with acs, so apply the fall back. */ + tui_border_kind_value = fallback; + tui_border_kind_value_reason = ", NCURSES_NO_UTF8_ACS unset"; +} + +static const char * +tui_border_kind (void) +{ + determine_tui_border_kind_value (); + return tui_border_kind_value; +} + static void show_tui_border_kind (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - gdb_printf (file, _("The kind of border for TUI windows is \"%s\".\n"), - value); + if (strcmp (tui_border_kind (), value) != 0) + { + gdb_printf (file, _("The kind of border for TUI windows is \"%s\" (%s%s).\n"), + value, tui_border_kind (), tui_border_kind_value_reason); + } + else + gdb_printf (file, _("The kind of border for TUI windows is \"%s\".\n"), + value); } /* Implementation of the "set/show style tui-current-position" commands. */ @@ -298,25 +365,25 @@ tui_update_variables () /* If one corner changes, all characters are changed. Only check the first one. The ACS characters are determined at run time by curses terminal management. */ - entry = translate (tui_border_kind, tui_border_kind_translate_lrcorner); + entry = translate (tui_border_kind (), tui_border_kind_translate_lrcorner); if (tui_border_lrcorner != (chtype) entry->value) { tui_border_lrcorner = (entry->value < 0) ? ACS_LRCORNER : entry->value; need_redraw = true; } - entry = translate (tui_border_kind, tui_border_kind_translate_llcorner); + entry = translate (tui_border_kind (), tui_border_kind_translate_llcorner); tui_border_llcorner = (entry->value < 0) ? ACS_LLCORNER : entry->value; - entry = translate (tui_border_kind, tui_border_kind_translate_ulcorner); + entry = translate (tui_border_kind (), tui_border_kind_translate_ulcorner); tui_border_ulcorner = (entry->value < 0) ? ACS_ULCORNER : entry->value; - entry = translate (tui_border_kind, tui_border_kind_translate_urcorner); + entry = translate (tui_border_kind (), tui_border_kind_translate_urcorner); tui_border_urcorner = (entry->value < 0) ? ACS_URCORNER : entry->value; - entry = translate (tui_border_kind, tui_border_kind_translate_hline); + entry = translate (tui_border_kind (), tui_border_kind_translate_hline); tui_border_hline = (entry->value < 0) ? ACS_HLINE : entry->value; - entry = translate (tui_border_kind, tui_border_kind_translate_vline); + entry = translate (tui_border_kind (), tui_border_kind_translate_vline); tui_border_vline = (entry->value < 0) ? ACS_VLINE : entry->value; return need_redraw; @@ -1204,13 +1271,15 @@ defaults to 1, and WIN defaults to the currently focused window.")); /* Define the tui control variables. */ add_setshow_enum_cmd ("border-kind", no_class, tui_border_kind_enums, - &tui_border_kind, _("\ + &tui_border_kind_setting, _("\ Set the kind of border for TUI windows."), _("\ Show the kind of border for TUI windows."), _("\ This variable controls the border of TUI windows:\n\ space use a white space\n\ ascii use ascii characters + - | for the border\n\ - acs use the Alternate Character Set"), + acs use the Alternate Character Set\n\ + acs-or-space detect if acs is possible, otherwise use space\n\ + acs-or-ascii detect if acs is possible, otherwise use ascii"), tui_set_var_cmd, show_tui_border_kind, &tui_setlist, &tui_showlist);