diff options
Diffstat (limited to 'gdb/tui')
-rw-r--r-- | gdb/tui/tui-layout.c | 15 | ||||
-rw-r--r-- | gdb/tui/tui-layout.h | 49 | ||||
-rw-r--r-- | gdb/tui/tui-win.c | 40 |
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 |