diff options
-rw-r--r-- | gdb/ChangeLog | 15 | ||||
-rw-r--r-- | gdb/NEWS | 4 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 37 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.tui/new-layout.exp | 54 | ||||
-rw-r--r-- | gdb/tui/tui-layout.c | 103 | ||||
-rw-r--r-- | gdb/tui/tui-layout.h | 9 |
8 files changed, 225 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a7e565a..ed2f358 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,20 @@ 2020-02-22 Tom Tromey <tom@tromey.com> + * NEWS: Add "tui new-layout" item. + * tui/tui-layout.c (add_layout_command): Return cmd_list_element. + Add new-layout command to help text. + (validate_window_name): New function. + (tui_new_layout_command): New function. + (_initialize_tui_layout): Register "new-layout". + (tui_layout_window::specification): New method. + (tui_layout_window::specification): New method. + * tui/tui-layout.h (class tui_layout_base) <specification>: New + method. + (class tui_layout_window) <specification>: New method. + (class tui_layout_split) <specification>: New method. + +2020-02-22 Tom Tromey <tom@tromey.com> + * tui/tui.c (tui_enable): Call tui_set_initial_layout. * tui/tui-win.c (window_name_completer): Update comment. * tui/tui-layout.h (class tui_layout_base) <replace_window>: @@ -30,6 +30,10 @@ show exec-file-mismatch -- Show exec-file-mismatch handling (ask|warn|off). whether to load the process executable file; if 'warn', just display a warning; if 'off', don't attempt to detect a mismatch. +tui new-layout NAME WINDOW WEIGHT [WINDOW WEIGHT]... + Define a new TUI layout, specifying its name and the windows that + will be displayed. + * New targets GNU/Linux/RISC-V (gdbserver) riscv*-*-linux* diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 4900480..99f2d93 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2020-02-22 Tom Tromey <tom@tromey.com> + + * gdb.texinfo (TUI Overview): Mention user layouts. + (TUI Commands): Document "tui new-layout". + 2020-01-26 Tom Tromey <tromey@adacore.com> * gdb.texinfo (M68K Features): Document floating-point feature diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a2866a2..c261738 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -27755,6 +27755,8 @@ source and registers, or assembly and registers. @end itemize +These are the standard layouts, but other layouts can be defined. + A status line above the command window shows the following information: @table @emph @@ -27991,11 +27993,40 @@ Disable TUI mode, returning to the console interpreter. @kindex info win List and give the size of all displayed windows. +@item tui new-layout @var{name} @var{window} @var{weight} @r{[}@var{window} @var{weight}@dots{}@r{]} +@kindex tui new-layout +Create a new TUI layout. The new layout will be named @var{name}, and +can be accessed using the @code{layout} command (see below). + +Each @var{window} parameter is the name of a window to display. The +windows will be displayed from top to bottom in the order listed. The +names of the windows are the same as the ones given to the +@code{focus} command (see below); additional, the @code{status} +window can be specified. + +Each @var{weight} is an integer. It is the weight of this window +relative to all the other windows in the layout. These numbers are +used to calculate how much of the screen is given to each window. + +For example: + +@example +(gdb) tui new-layout example src 1 regs 1 status 0 cmd 1 +@end example + +Here, the new layout is called @samp{example}. It shows the source +and register windows, followed by the status window, and then finally +the command window. The non-status windows all have the same weight, +so the terminal will be split into three roughly equal sections. + @item layout @var{name} @kindex layout -Changes which TUI windows are displayed. In each layout the command -window is always displayed, the @var{name} parameter controls which -additional windows are displayed, and can be any of the following: +Changes which TUI windows are displayed. The @var{name} parameter +controls which layout is shown. It can be either one of the built-in +layout names, or the name of a layout defined by the user using +@code{tui new-layout}. + +The built-in layouts are as follows: @table @code @item next diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index d3f555e..c7270b9 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2020-02-22 Tom Tromey <tom@tromey.com> + * gdb.tui/new-layout.exp: New file. + +2020-02-22 Tom Tromey <tom@tromey.com> + * gdb.rust/rust-style.rs: New file. * gdb.rust/rust-style.exp: New file. * gdb.base/style.exp: Test structure printing. diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp new file mode 100644 index 0000000..2efc172 --- /dev/null +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -0,0 +1,54 @@ +# Copyright 2020 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 <http://www.gnu.org/licenses/>. + +# Test "tui new-layout". + +load_lib "tuiterm.exp" + +standard_testfile tui-layout.c + +if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} { + return -1 +} + +Term::clean_restart 24 80 $testfile + +gdb_test "tui new-layout" \ + "No layout name specified" +gdb_test "tui new-layout example" \ + "New layout does not contain any windows" +gdb_test "tui new-layout example zzq" \ + "Unknown window \"zzq\"" +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_no_output "tui new-layout example asm 1 status 0 cmd 1" + +gdb_test "help layout example" \ + "Apply the \"example\" layout.*tui new-layout example asm 1 status 0 cmd 1" + +if {![Term::enter_tui]} { + unsupported "TUI not supported" +} + +set text [Term::get_all_lines] +gdb_assert {![string match "No Source Available" $text]} \ + "initial source listing" + +Term::command "layout example" +Term::check_contents "example layout shows assembly" \ + "No Assembly Available" diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c index e2ddbfb..8f5dd6e 100644 --- a/gdb/tui/tui-layout.c +++ b/gdb/tui/tui-layout.c @@ -27,7 +27,9 @@ #include "source.h" #include "cli/cli-cmds.h" #include "cli/cli-decode.h" +#include "cli/cli-utils.h" #include <ctype.h> +#include <unordered_set> #include "tui/tui.h" #include "tui/tui-command.h" @@ -397,6 +399,14 @@ tui_layout_window::replace_window (const char *name, const char *new_window) /* See tui-layout.h. */ +void +tui_layout_window::specification (ui_file *output) +{ + fputs_unfiltered (get_name (), output); +} + +/* See tui-layout.h. */ + tui_layout_split * tui_layout_split::add_split (int weight) { @@ -698,6 +708,22 @@ tui_layout_split::replace_window (const char *name, const char *new_window) item.layout->replace_window (name, new_window); } +/* See tui-layout.h. */ + +void +tui_layout_split::specification (ui_file *output) +{ + bool first = true; + for (auto &item : m_splits) + { + if (!first) + fputs_unfiltered (" ", output); + first = false; + item.layout->specification (output); + fprintf_unfiltered (output, " %d", item.weight); + } +} + /* Destroy the layout associated with SELF. */ static void @@ -714,13 +740,19 @@ static struct cmd_list_element *layout_list; /* Add a "layout" command with name NAME that switches to LAYOUT. */ -static void +static struct cmd_list_element * add_layout_command (const char *name, tui_layout_split *layout) { struct cmd_list_element *cmd; - gdb::unique_xmalloc_ptr<char> doc (xstrprintf (_("Apply the \"%s\" layout"), - name)); + string_file spec; + layout->specification (&spec); + + gdb::unique_xmalloc_ptr<char> doc + (xstrprintf (_("Apply the \"%s\" layout.\n\ +This layout was created using:\n\ + tui new-layout %s %s"), + name, name, spec.c_str ())); cmd = add_cmd (name, class_tui, nullptr, doc.get (), &layout_list); set_cmd_context (cmd, layout); @@ -730,6 +762,8 @@ add_layout_command (const char *name, tui_layout_split *layout) cmd->doc_allocated = 1; doc.release (); layouts.emplace_back (layout); + + return cmd; } /* Initialize the standard layouts. */ @@ -777,6 +811,59 @@ initialize_layouts () +/* A helper function that returns true if NAME is the name of an + available window. */ + +static bool +validate_window_name (const std::string &name) +{ + return (name == "src" || name == "cmd" + || name == "regs" || name == "asm" + || name == "status"); +} + +/* Implementation of the "tui new-layout" command. */ + +static void +tui_new_layout_command (const char *spec, int from_tty) +{ + std::string new_name = extract_arg (&spec); + if (new_name.empty ()) + error (_("No layout name specified")); + if (new_name[0] == '-') + error (_("Layout name cannot start with '-'")); + + std::unique_ptr<tui_layout_split> new_layout (new tui_layout_split); + std::unordered_set<std::string> seen_windows; + while (true) + { + std::string 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 (seen_windows.empty ()) + error (_("New layout does not contain any windows")); + if (seen_windows.find ("cmd") == seen_windows.end ()) + error (_("New layout does not contain the \"cmd\" window")); + + gdb::unique_xmalloc_ptr<char> cmd_name + = make_unique_xstrdup (new_name.c_str ()); + struct cmd_list_element *cmd + = add_layout_command (cmd_name.get (), new_layout.get ()); + cmd->name_allocated = 1; + cmd_name.release (); + new_layout.release (); +} + /* Base command for "layout". */ static void @@ -807,5 +894,15 @@ Usage: layout prev | next | LAYOUT-NAME"), _("Apply the TUI register layout"), &layout_list); + add_cmd ("new-layout", class_tui, tui_new_layout_command, + _("Create a new TUI layout.\n\ +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\ +Each WEIGHT is an integer, which holds the relative size\n\ +to be allocated to the window."), + tui_get_cmd_list ()); + initialize_layouts (); } diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h index 98bd548..c2249a7 100644 --- a/gdb/tui/tui-layout.h +++ b/gdb/tui/tui-layout.h @@ -22,6 +22,8 @@ #ifndef TUI_TUI_LAYOUT_H #define TUI_TUI_LAYOUT_H +#include "ui-file.h" + #include "tui/tui.h" #include "tui/tui-data.h" @@ -72,6 +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; + /* The most recent space allocation. */ int x = 0; int y = 0; @@ -120,6 +125,8 @@ public: void replace_window (const char *name, const char *new_window) override; + void specification (ui_file *output) override; + protected: void get_sizes (int *min_height, int *max_height) override; @@ -167,6 +174,8 @@ public: void replace_window (const char *name, const char *new_window) override; + void specification (ui_file *output) override; + protected: void get_sizes (int *min_height, int *max_height) override; |