mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 12:23:31 +08:00
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
This commit is contained in:
@ -1,3 +1,17 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
2020-02-22 Tom Tromey <tom@tromey.com>
|
2020-02-22 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
* NEWS: Add "tui new-layout" item.
|
* NEWS: Add "tui new-layout" item.
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2020-02-22 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
|
* gdb.tui/new-layout.exp: Add sub-layout tests.
|
||||||
|
|
||||||
2020-02-22 Tom Tromey <tom@tromey.com>
|
2020-02-22 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
* gdb.tui/new-layout.exp: New file.
|
* gdb.tui/new-layout.exp: New file.
|
||||||
|
@ -35,12 +35,23 @@ gdb_test "tui new-layout example src 1 src 1" \
|
|||||||
"Window \"src\" seen twice in layout"
|
"Window \"src\" seen twice in layout"
|
||||||
gdb_test "tui new-layout example src 1" \
|
gdb_test "tui new-layout example src 1" \
|
||||||
"New layout does not contain the \"cmd\" window"
|
"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 status 0 cmd 1"
|
gdb_test_no_output "tui new-layout example asm 1 status 0 cmd 1"
|
||||||
|
|
||||||
gdb_test "help layout example" \
|
gdb_test "help layout example" \
|
||||||
"Apply the \"example\" layout.*tui new-layout example asm 1 status 0 cmd 1"
|
"Apply the \"example\" layout.*tui new-layout example asm 1 status 0 cmd 1"
|
||||||
|
|
||||||
|
gdb_test_no_output "tui new-layout example2 {asm 1 status 0} 1 cmd 1"
|
||||||
|
|
||||||
|
gdb_test "help layout example2" \
|
||||||
|
"Apply the \"example2\" layout.*tui new-layout example2 {asm 1 status 0} 1 cmd 1"
|
||||||
|
|
||||||
if {![Term::enter_tui]} {
|
if {![Term::enter_tui]} {
|
||||||
unsupported "TUI not supported"
|
unsupported "TUI not supported"
|
||||||
}
|
}
|
||||||
|
@ -400,20 +400,19 @@ tui_layout_window::replace_window (const char *name, const char *new_window)
|
|||||||
/* See tui-layout.h. */
|
/* See tui-layout.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
tui_layout_window::specification (ui_file *output)
|
tui_layout_window::specification (ui_file *output, int depth)
|
||||||
{
|
{
|
||||||
fputs_unfiltered (get_name (), output);
|
fputs_unfiltered (get_name (), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See tui-layout.h. */
|
/* See tui-layout.h. */
|
||||||
|
|
||||||
tui_layout_split *
|
void
|
||||||
tui_layout_split::add_split (int weight)
|
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::move (layout)};
|
||||||
split s = {weight, std::unique_ptr<tui_layout_base> (result)};
|
|
||||||
m_splits.push_back (std::move (s));
|
m_splits.push_back (std::move (s));
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See tui-layout.h. */
|
/* See tui-layout.h. */
|
||||||
@ -711,17 +710,23 @@ tui_layout_split::replace_window (const char *name, const char *new_window)
|
|||||||
/* See tui-layout.h. */
|
/* See tui-layout.h. */
|
||||||
|
|
||||||
void
|
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;
|
bool first = true;
|
||||||
for (auto &item : m_splits)
|
for (auto &item : m_splits)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (!first)
|
||||||
fputs_unfiltered (" ", output);
|
fputs_unfiltered (" ", output);
|
||||||
first = false;
|
first = false;
|
||||||
item.layout->specification (output);
|
item.layout->specification (output, depth + 1);
|
||||||
fprintf_unfiltered (output, " %d", item.weight);
|
fprintf_unfiltered (output, " %d", item.weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (depth > 0)
|
||||||
|
fputs_unfiltered ("}", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy the layout associated with SELF. */
|
/* 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;
|
struct cmd_list_element *cmd;
|
||||||
|
|
||||||
string_file spec;
|
string_file spec;
|
||||||
layout->specification (&spec);
|
layout->specification (&spec, 0);
|
||||||
|
|
||||||
gdb::unique_xmalloc_ptr<char> doc
|
gdb::unique_xmalloc_ptr<char> doc
|
||||||
(xstrprintf (_("Apply the \"%s\" layout.\n\
|
(xstrprintf (_("Apply the \"%s\" layout.\n\
|
||||||
@ -833,23 +838,60 @@ tui_new_layout_command (const char *spec, int from_tty)
|
|||||||
if (new_name[0] == '-')
|
if (new_name[0] == '-')
|
||||||
error (_("Layout name cannot start with '-'"));
|
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;
|
std::unordered_set<std::string> seen_windows;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
std::string name = extract_arg (&spec);
|
spec = skip_spaces (spec);
|
||||||
if (name.empty ())
|
if (spec[0] == '\0')
|
||||||
break;
|
break;
|
||||||
if (!validate_window_name (name))
|
|
||||||
error (_("Unknown window \"%s\""), name.c_str ());
|
if (spec[0] == '{')
|
||||||
if (seen_windows.find (name) != seen_windows.end ())
|
{
|
||||||
error (_("Window \"%s\" seen twice in layout"), name.c_str ());
|
splits.emplace_back (new tui_layout_split);
|
||||||
ULONGEST weight = get_ulongest (&spec);
|
++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)
|
if ((int) weight != weight)
|
||||||
error (_("Weight out of range: %s"), pulongest (weight));
|
error (_("Weight out of range: %s"), pulongest (weight));
|
||||||
new_layout->add_window (name.c_str (), weight);
|
if (is_close)
|
||||||
seen_windows.insert (name);
|
{
|
||||||
|
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 ())
|
if (seen_windows.empty ())
|
||||||
error (_("New layout does not contain any windows"));
|
error (_("New layout does not contain any windows"));
|
||||||
if (seen_windows.find ("cmd") == seen_windows.end ())
|
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
|
gdb::unique_xmalloc_ptr<char> cmd_name
|
||||||
= make_unique_xstrdup (new_name.c_str ());
|
= make_unique_xstrdup (new_name.c_str ());
|
||||||
|
std::unique_ptr<tui_layout_split> new_layout = std::move (splits.back ());
|
||||||
struct cmd_list_element *cmd
|
struct cmd_list_element *cmd
|
||||||
= add_layout_command (cmd_name.get (), new_layout.get ());
|
= add_layout_command (cmd_name.get (), new_layout.get ());
|
||||||
cmd->name_allocated = 1;
|
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\
|
Create a new TUI layout. The new layout will be named NAME,\n\
|
||||||
and can be accessed using \"layout NAME\".\n\
|
and can be accessed using \"layout NAME\".\n\
|
||||||
The windows will be displayed in the specified order.\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\
|
Each WEIGHT is an integer, which holds the relative size\n\
|
||||||
to be allocated to the window."),
|
to be allocated to the window."),
|
||||||
tui_get_cmd_list ());
|
tui_get_cmd_list ());
|
||||||
|
@ -74,8 +74,9 @@ public:
|
|||||||
NEW_WINDOW. */
|
NEW_WINDOW. */
|
||||||
virtual void replace_window (const char *name, const char *new_window) = 0;
|
virtual void replace_window (const char *name, const char *new_window) = 0;
|
||||||
|
|
||||||
/* Append the specification to this window to OUTPUT. */
|
/* Append the specification to this window to OUTPUT. DEPTH is the
|
||||||
virtual void specification (ui_file *output) = 0;
|
depth of this layout in the hierarchy (zero-based). */
|
||||||
|
virtual void specification (ui_file *output, int depth) = 0;
|
||||||
|
|
||||||
/* The most recent space allocation. */
|
/* The most recent space allocation. */
|
||||||
int x = 0;
|
int x = 0;
|
||||||
@ -125,7 +126,7 @@ public:
|
|||||||
|
|
||||||
void replace_window (const char *name, const char *new_window) override;
|
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:
|
protected:
|
||||||
|
|
||||||
@ -153,7 +154,7 @@ public:
|
|||||||
/* Add a new split layout to this layout. WEIGHT is the desired
|
/* Add a new split layout to this layout. WEIGHT is the desired
|
||||||
size, which is relative to the other weights given in this
|
size, which is relative to the other weights given in this
|
||||||
layout. */
|
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
|
/* 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
|
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 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:
|
protected:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user