diff options
author | Tom Tromey <tom@tromey.com> | 2020-02-22 11:48:26 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2020-02-22 11:48:32 -0700 |
commit | c22fef7e4cf9d3cb6d7062d248b0cc148dc76137 (patch) | |
tree | 2295fbbb70ac4b3d646269a08bb6437b46420555 /gdb/tui | |
parent | ee325b61cd4389506d2dd63294c1ce1c64cb9d9f (diff) | |
download | binutils-gdb-c22fef7e4cf9d3cb6d7062d248b0cc148dc76137.tar.gz |
Allow TUI sub-layouts in "new-layout" command
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-02-22 Tom Tromey <tom@tromey.com>
* tui/tui-layout.h (class tui_layout_split) <add_split>: Change
parameter and return types.
(class tui_layout_base) <specification>: Add "depth".
(class tui_layout_window) <specification>: Add "depth".
(class tui_layout_split) <specification>: 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-02-22 Tom Tromey <tom@tromey.com>
* gdb.tui/new-layout.exp: Add sub-layout tests.
Change-Id: Iddf52d067a552c168b8a67f29caf7ac86404b10c
Diffstat (limited to 'gdb/tui')
-rw-r--r-- | gdb/tui/tui-layout.c | 84 | ||||
-rw-r--r-- | gdb/tui/tui-layout.h | 11 |
2 files changed, 71 insertions, 24 deletions
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index 8f5dd6ec516..6077a9cc68c 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<tui_layout_split> &&layout, + int weight) { - tui_layout_split *result = new tui_layout_split (); - split s = {weight, std::unique_ptr<tui_layout_base> (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<char> 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<tui_layout_split> new_layout (new tui_layout_split); + std::vector<std::unique_ptr<tui_layout_split>> splits; + splits.emplace_back (new tui_layout_split); std::unordered_set<std::string> 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<tui_layout_split> 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<char> cmd_name = make_unique_xstrdup (new_name.c_str ()); + std::unique_ptr<tui_layout_split> new_layout = std::move (splits.back ()); struct cmd_list_element *cmd = add_layout_command (cmd_name.get (), new_layout.get ()); cmd->name_allocated = 1; @@ -900,6 +943,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<tui_layout_split> &&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: |