From patchwork Sat Jan 4 18:33:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 37179 Received: (qmail 130815 invoked by alias); 4 Jan 2020 18:34:21 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 130714 invoked by uid 89); 4 Jan 2020 18:34:20 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=first X-HELO: gateway22.websitewelcome.com Received: from gateway22.websitewelcome.com (HELO gateway22.websitewelcome.com) (192.185.47.228) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 04 Jan 2020 18:34:16 +0000 Received: from cm13.websitewelcome.com (cm13.websitewelcome.com [100.42.49.6]) by gateway22.websitewelcome.com (Postfix) with ESMTP id ECF7C49FA8 for ; Sat, 4 Jan 2020 12:34:14 -0600 (CST) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id noFaiCiLV3Qi0noFai0thx; Sat, 04 Jan 2020 12:34:14 -0600 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=CEoggI6O8k0f3ZZZP969SiTekioXQ+9FJC9+T5kYlF8=; b=Zo55jaWQbeLNQJYTmICjpeVdfE Mf8XiJ9zb7XbF7/dU0OOPCYdnB4QQjAjGr328j3jMDvG6EgXYy/thG432lB1uVHNaeePiu061yL5i Messcqq0p85QiZIWwuJMdPoXE; Received: from 75-166-123-50.hlrn.qwest.net ([75.166.123.50]:48942 helo=bapiya.Home) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92) (envelope-from ) id 1inoFa-0026Lh-Pb; Sat, 04 Jan 2020 11:34:14 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 09/24] Allow TUI sub-layouts in "new-layout" command Date: Sat, 4 Jan 2020 11:33:55 -0700 Message-Id: <20200104183410.17114-10-tom@tromey.com> In-Reply-To: <20200104183410.17114-1-tom@tromey.com> References: <20200104183410.17114-1-tom@tromey.com> The new TUI layout engine has support for "sub-layouts" -- this is a layout that includes another layout as a child. A sub-layout is treated as a unit when allocating space. There's not a very strong reason to use sub-layouts currently. This patch exists to introduce the idea, and to simplify the subsequent patch that adds horizontal layouts -- where sub-layouts are needed. Because this patch won't go in on its own, I chose to defer documenting this change until the subsequent horizontal layout patch. gdb/ChangeLog 2020-01-04 Tom Tromey * tui/tui-layout.h (class tui_layout_split) : Change parameter and return types. (class tui_layout_base) : Add "depth". (class tui_layout_window) : Add "depth". (class tui_layout_split) : Add "depth". * tui/tui-layout.c (tui_layout_split::add_split): Change parameter and return types. (tui_new_layout_command): Parse sub-layouts. (_initialize_tui_layout): Update help string. (tui_layout_window::specification): Add "depth". (add_layout_command): Update. gdb/testsuite/ChangeLog 2020-01-04 Tom Tromey * gdb.tui/new-layout.exp: Add sub-layout tests. Change-Id: Iddf52d067a552c168b8a67f29caf7ac86404b10c --- gdb/ChangeLog | 14 +++++ gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.tui/new-layout.exp | 11 ++++ gdb/tui/tui-layout.c | 84 +++++++++++++++++++++------- gdb/tui/tui-layout.h | 11 ++-- 5 files changed, 100 insertions(+), 24 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index 8475a9db295..406d9b25f08 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -35,12 +35,23 @@ gdb_test "tui new-layout example src 1 src 1" \ "Window \"src\" seen twice in layout" gdb_test "tui new-layout example src 1" \ "New layout does not contain the \"cmd\" window" +gdb_test "tui new-layout example src 1}" \ + "Extra '}' in layout specification" +gdb_test "tui new-layout example {src 1} 1}" \ + "Extra '}' in layout specification" +gdb_test "tui new-layout example {src 1" \ + "Missing '}' in layout specification" gdb_test_no_output "tui new-layout example asm 1 locator 0 cmd 1" gdb_test "help layout example" \ "Apply the \"example\" layout.*tui new-layout example asm 1 locator 0 cmd 1" +gdb_test_no_output "tui new-layout example2 {asm 1 locator 0} 1 cmd 1" + +gdb_test "help layout example2" \ + "Apply the \"example2\" layout.*tui new-layout example2 {asm 1 locator 0} 1 cmd 1" + if {![Term::enter_tui]} { unsupported "TUI not supported" } diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 438a3a03828..3604d7e06bc 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -400,20 +400,19 @@ tui_layout_window::replace_window (const char *name, const char *new_window) /* See tui-layout.h. */ void -tui_layout_window::specification (ui_file *output) +tui_layout_window::specification (ui_file *output, int depth) { fputs_unfiltered (get_name (), output); } /* See tui-layout.h. */ -tui_layout_split * -tui_layout_split::add_split (int weight) +void +tui_layout_split::add_split (std::unique_ptr &&layout, + int weight) { - tui_layout_split *result = new tui_layout_split (); - split s = {weight, std::unique_ptr (result)}; + split s = {weight, std::move (layout)}; m_splits.push_back (std::move (s)); - return result; } /* See tui-layout.h. */ @@ -711,17 +710,23 @@ tui_layout_split::replace_window (const char *name, const char *new_window) /* See tui-layout.h. */ void -tui_layout_split::specification (ui_file *output) +tui_layout_split::specification (ui_file *output, int depth) { + if (depth > 0) + fputs_unfiltered ("{", output); + bool first = true; for (auto &item : m_splits) { if (!first) fputs_unfiltered (" ", output); first = false; - item.layout->specification (output); + item.layout->specification (output, depth + 1); fprintf_unfiltered (output, " %d", item.weight); } + + if (depth > 0) + fputs_unfiltered ("}", output); } /* Destroy the layout associated with SELF. */ @@ -746,7 +751,7 @@ add_layout_command (const char *name, tui_layout_split *layout) struct cmd_list_element *cmd; string_file spec; - layout->specification (&spec); + layout->specification (&spec, 0); gdb::unique_xmalloc_ptr doc (xstrprintf (_("Apply the \"%s\" layout.\n\ @@ -833,23 +838,60 @@ tui_new_layout_command (const char *spec, int from_tty) if (new_name[0] == '-') error (_("Layout name cannot start with '-'")); - std::unique_ptr new_layout (new tui_layout_split); + std::vector> splits; + splits.emplace_back (new tui_layout_split); std::unordered_set seen_windows; while (true) { - std::string name = extract_arg (&spec); - if (name.empty ()) + spec = skip_spaces (spec); + if (spec[0] == '\0') break; - if (!validate_window_name (name)) - error (_("Unknown window \"%s\""), name.c_str ()); - if (seen_windows.find (name) != seen_windows.end ()) - error (_("Window \"%s\" seen twice in layout"), name.c_str ()); - ULONGEST weight = get_ulongest (&spec); + + if (spec[0] == '{') + { + splits.emplace_back (new tui_layout_split); + ++spec; + continue; + } + + bool is_close = false; + std::string name; + if (spec[0] == '}') + { + is_close = true; + ++spec; + if (splits.size () == 1) + error (_("Extra '}' in layout specification")); + } + else + { + name = extract_arg (&spec); + if (name.empty ()) + break; + if (!validate_window_name (name)) + error (_("Unknown window \"%s\""), name.c_str ()); + if (seen_windows.find (name) != seen_windows.end ()) + error (_("Window \"%s\" seen twice in layout"), name.c_str ()); + } + + ULONGEST weight = get_ulongest (&spec, '}'); if ((int) weight != weight) error (_("Weight out of range: %s"), pulongest (weight)); - new_layout->add_window (name.c_str (), weight); - seen_windows.insert (name); + if (is_close) + { + std::unique_ptr last_split + = std::move (splits.back ()); + splits.pop_back (); + splits.back ()->add_split (std::move (last_split), weight); + } + else + { + splits.back ()->add_window (name.c_str (), weight); + seen_windows.insert (name); + } } + if (splits.size () > 1) + error (_("Missing '}' in layout specification")); if (seen_windows.empty ()) error (_("New layout does not contain any windows")); if (seen_windows.find ("cmd") == seen_windows.end ()) @@ -857,6 +899,7 @@ tui_new_layout_command (const char *spec, int from_tty) gdb::unique_xmalloc_ptr cmd_name = make_unique_xstrdup (new_name.c_str ()); + std::unique_ptr new_layout = std::move (splits.back ()); struct cmd_list_element *cmd = add_layout_command (cmd_name.get (), new_layout.get ()); cmd->name_allocated = 1; @@ -899,6 +942,9 @@ Usage: tui new-layout NAME WINDOW WEIGHT [WINDOW WEIGHT]...\n\ Create a new TUI layout. The new layout will be named NAME,\n\ and can be accessed using \"layout NAME\".\n\ The windows will be displayed in the specified order.\n\ +A WINDOW can also be of the form:\n\ + { NAME WEIGHT [NAME WEIGHT]... }\n\ +This form indicates a sub-frame.\n\ Each WEIGHT is an integer, which holds the relative size\n\ to be allocated to the window."), tui_get_cmd_list ()); diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index c2249a783f8..4351e260720 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -74,8 +74,9 @@ public: NEW_WINDOW. */ virtual void replace_window (const char *name, const char *new_window) = 0; - /* Append the specification to this window to OUTPUT. */ - virtual void specification (ui_file *output) = 0; + /* Append the specification to this window to OUTPUT. DEPTH is the + depth of this layout in the hierarchy (zero-based). */ + virtual void specification (ui_file *output, int depth) = 0; /* The most recent space allocation. */ int x = 0; @@ -125,7 +126,7 @@ public: void replace_window (const char *name, const char *new_window) override; - void specification (ui_file *output) override; + void specification (ui_file *output, int depth) override; protected: @@ -153,7 +154,7 @@ public: /* Add a new split layout to this layout. WEIGHT is the desired size, which is relative to the other weights given in this layout. */ - tui_layout_split *add_split (int weight); + void add_split (std::unique_ptr &&layout, int weight); /* Add a new window to this layout. NAME is the name of the window to add. WEIGHT is the desired size, which is relative to the @@ -174,7 +175,7 @@ public: void replace_window (const char *name, const char *new_window) override; - void specification (ui_file *output) override; + void specification (ui_file *output, int depth) override; protected: