aboutsummaryrefslogtreecommitdiff
path: root/gdb/tui
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2020-02-22 11:48:26 -0700
committerTom Tromey <tom@tromey.com>2020-02-22 11:48:31 -0700
commitee325b61cd4389506d2dd63294c1ce1c64cb9d9f (patch)
tree1040c49dcd59346665afe89f07cfc62d2d0317ad /gdb/tui
parent416eb92d84ac0bc4b8aba137789f52d1f987cd54 (diff)
downloadbinutils-ee325b61cd4389506d2dd63294c1ce1c64cb9d9f.zip
binutils-ee325b61cd4389506d2dd63294c1ce1c64cb9d9f.tar.gz
binutils-ee325b61cd4389506d2dd63294c1ce1c64cb9d9f.tar.bz2
Add the "tui new-layout" command
This adds a new command, "tui new-layout". This command can be used to define a new TUI window layout. The command is used like: (gdb) tui new-layout name src 1 regs 1 status 0 cmd 1 The first argument is the name of the layout. In this example, it is "name", so the new layout could be seen by "layout name". Subsequent arguments come in pairs, where the first item in a pair is the name of a window, and the second item in a pair is the window's weight. A weight is just an integer -- a window's allocated size is proportional to the total of the weights given. So, in the above example, all windows will have the same size (the status windows's weight does not matter, because it has fixed height). gdb/ChangeLog 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. gdb/doc/ChangeLog 2020-02-22 Tom Tromey <tom@tromey.com> * gdb.texinfo (TUI Overview): Mention user layouts. (TUI Commands): Document "tui new-layout". gdb/testsuite/ChangeLog 2020-02-22 Tom Tromey <tom@tromey.com> * gdb.tui/new-layout.exp: New file. Change-Id: Id7c3ace20ab1e8924f8f4ad788f40210f58a5c05
Diffstat (limited to 'gdb/tui')
-rw-r--r--gdb/tui/tui-layout.c103
-rw-r--r--gdb/tui/tui-layout.h9
2 files changed, 109 insertions, 3 deletions
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;