aboutsummaryrefslogtreecommitdiff
path: root/gdb/tui
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/tui')
-rw-r--r--gdb/tui/tui-layout.c15
-rw-r--r--gdb/tui/tui-layout.h49
-rw-r--r--gdb/tui/tui-win.c40
3 files changed, 99 insertions, 5 deletions
diff --git a/gdb/tui/tui-layout.c b/gdb/tui/tui-layout.c
index 27abee0..ecdcd48 100644
--- a/gdb/tui/tui-layout.c
+++ b/gdb/tui/tui-layout.c
@@ -29,7 +29,6 @@
#include "cli/cli-decode.h"
#include "cli/cli-utils.h"
#include <ctype.h>
-#include <unordered_map>
#include <unordered_set>
#include "tui/tui.h"
@@ -351,7 +350,17 @@ make_standard_window (const char *)
shut down, causing crashes if any window destruction requires
running Python code. */
-static std::unordered_map<std::string, window_factory> *known_window_types;
+static window_types_map *known_window_types;
+
+/* See tui-layout.h. */
+
+known_window_names_range
+all_known_window_names ()
+{
+ auto begin = known_window_names_iterator (known_window_types->begin ());
+ auto end = known_window_names_iterator (known_window_types->end ());
+ return known_window_names_range (begin, end);
+}
/* Helper function that returns a TUI window, given its name. */
@@ -377,7 +386,7 @@ tui_get_window_by_name (const std::string &name)
static void
initialize_known_windows ()
{
- known_window_types = new std::unordered_map<std::string, window_factory>;
+ known_window_types = new window_types_map;
known_window_types->emplace (SRC_NAME,
make_standard_window<SRC_WIN,
diff --git a/gdb/tui/tui-layout.h b/gdb/tui/tui-layout.h
index 206f111..ff354fb 100644
--- a/gdb/tui/tui-layout.h
+++ b/gdb/tui/tui-layout.h
@@ -26,6 +26,9 @@
#include "tui/tui.h"
#include "tui/tui-data.h"
+#include "gdbsupport/iterator-range.h"
+
+#include <unordered_map>
/* Values that can be returned when handling a request to adjust a
window's size. */
@@ -358,10 +361,56 @@ extern void tui_adjust_window_width (struct tui_win_info *win,
typedef std::function<tui_win_info * (const char *name)> window_factory;
+/* The type for a data structure that maps a window name to that window's
+ factory function. */
+typedef std::unordered_map<std::string, window_factory> window_types_map;
+
/* Register a new TUI window type. NAME is the name of the window
type. FACTORY is a function that can be called to instantiate the
window. */
extern void tui_register_window (const char *name, window_factory &&factory);
+/* An iterator class that exposes just the window names from the
+ known_window_types map in tui-layout.c. This is just a wrapper around
+ an iterator of the underlying known_window_types map, but this just
+ exposes the window names. */
+
+struct known_window_names_iterator
+{
+ using known_window_types_iterator = window_types_map::iterator;
+
+ known_window_names_iterator (known_window_types_iterator &&iter)
+ : m_iter (std::move (iter))
+ { /* Nothing. */ }
+
+ known_window_names_iterator &operator++ ()
+ {
+ ++m_iter;
+ return *this;
+ }
+
+ const std::string &operator* () const
+ { return (*m_iter).first; }
+
+ bool operator!= (const known_window_names_iterator &other) const
+ { return m_iter != other.m_iter; }
+
+private:
+
+ /* The underlying iterator. */
+ known_window_types_iterator m_iter;
+};
+
+/* A range adapter that makes it possible to iterate over the names of all
+ known tui windows. */
+
+using known_window_names_range
+ = iterator_range<known_window_names_iterator>;
+
+/* Return a range that can be used to walk over the name of all known tui
+ windows in a range-for loop. */
+
+extern known_window_names_range all_known_window_names ();
+
#endif /* TUI_TUI_LAYOUT_H */
diff --git a/gdb/tui/tui-win.c b/gdb/tui/tui-win.c
index 492a519..008189e 100644
--- a/gdb/tui/tui-win.c
+++ b/gdb/tui/tui-win.c
@@ -728,8 +728,44 @@ tui_set_focus_command (const char *arg, int from_tty)
else
win_info = tui_partial_win_by_name (arg);
- if (win_info == NULL)
- error (_("Unrecognized window name \"%s\""), arg);
+ if (win_info == nullptr)
+ {
+ /* When WIN_INFO is nullptr this can either mean that the window name
+ is unknown to GDB, or that the window is not in the current
+ layout. To try and help the user, give a different error
+ depending on which of these is the case. */
+ std::string matching_window_name;
+ bool is_ambiguous = false;
+
+ for (const std::string &name : all_known_window_names ())
+ {
+ /* Look through all windows in the current layout, if the window
+ is in the current layout then we're not interested is it. */
+ for (tui_win_info *item : all_tui_windows ())
+ if (item->name () == name)
+ continue;
+
+ if (startswith (name, arg))
+ {
+ if (matching_window_name.empty ())
+ matching_window_name = name;
+ else
+ is_ambiguous = true;
+ }
+ };
+
+ if (!matching_window_name.empty ())
+ {
+ if (is_ambiguous)
+ error (_("No windows matching \"%s\" in the current layout"),
+ arg);
+ else
+ error (_("Window \"%s\" is not in the current layout"),
+ matching_window_name.c_str ());
+ }
+ else
+ error (_("Unrecognized window name \"%s\""), arg);
+ }
/* If a window is part of the current layout then it will have a
tui_win_info associated with it and be visible, otherwise, there will