def setup()

in ec2rlcore/menu.py [0:0]


    def setup(self, stdscr):
        """
        Draw the menu and handle keyboard input.

        Parameters:
            stdscr (WindowObject): the screen; handled by curses.wrapper

        Returns:
            the string representing the currently selected row
        """

        # Initialize the WindowObject
        stdscr.clear()
        stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()

        # Start color support if supported
        if curses.has_colors():
            curses.start_color()

        # Initialize color pairs
        # Main window
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        # Sub-windows
        curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_WHITE)

        # Verify this is a terminal that is at least both 80 columns and 24 lines
        if curses.LINES < 24 or curses.COLS < 80:
            raise curses.error(
                "Required minimum terminal dimensions of 80x24 > {}x{}.".format(curses.COLS, curses.LINES))

        main_window, screen, footer = self.draw_menu(stdscr)

        # Menu loop until item is chosen with the <enter> key or the user quits with "q"
        while True:
            # Get a character from the keyboard
            key = stdscr.getch()
            # Enter selects the highlighted item
            if key == ord("\n"):
                footer_selection = self.footer_items[self.current_column]
                if footer_selection == "Select":
                    if isinstance(self._items[self.current_row - 1], (ec2rlcore.menu_item.ExitItem,
                                                                      ec2rlcore.menu_item.RunItem)):
                        self._items[self.current_row - 1]()
                        self.current_row = 1
                        self.current_column = 0
                        self.current_page = 1
                        self.done = True
                        return
                    else:
                        self.current_column = 0
                        return self._items[self.current_row - 1]()
                elif footer_selection == "Exit":
                    self.current_row = 1
                    self.current_column = 0
                    self.current_page = 1
                    self.done = True
                    return
                elif footer_selection == "Help":
                    self.current_column = 0
                    return self.show_item_help(self._items[self.current_row - 1])
                elif footer_selection == "Clear":
                    if isinstance(self._items[self.current_row - 1], ec2rlcore.menu_item.TextEntryItem):
                        self._items[self.current_row - 1].row_right = ""
                else:
                    raise MenuUnsupportedFooterOptionError(footer_selection)
            elif key == ord(" "):
                if isinstance(self._items[self.current_row - 1], ec2rlcore.menu_item.ToggleItem):
                    self._items[self.current_row - 1]()
            elif key in (78, "N"):
                # Select/deselect all ToggleItems in current menu
                for item in self._items:
                    if isinstance(item, ec2rlcore.menu_item.ToggleItem) \
                            and ((self.toggle_state and item.toggled) or (not self.toggle_state and not item.toggled)):
                        item()
                self.toggle_state = not self.toggle_state
            elif key in (260, curses.KEY_LEFT):
                if self.current_column > 0:
                    self.current_column -= 1
            # The right arrow key selects the footer option to the right of the currently selected item
            elif key in (261, curses.KEY_RIGHT):
                if self.current_column < self.num_columns - 1:
                    self.current_column += 1
            # The down arrow key selects the next option in the menu window and increments the page as needed
            elif key in (65, 258, curses.KEY_DOWN):
                if self.current_page == 1:
                    if self.current_row < self.max_displayed_rows and \
                                            self.current_row < self.num_rows:
                        self.current_row += 1
                    # Else + if num_pages > 1
                    elif self.num_pages > 1:
                        self.current_page += 1
                        self.current_row = 1 + (self.max_displayed_rows * (self.current_page - 1))
                elif self.current_page == self.num_pages:
                    if self.current_row < self.num_rows:
                        self.current_row += 1
                else:
                    if self.current_row < self.max_displayed_rows + \
                            (self.max_displayed_rows * (self.current_page - 1)):
                        self.current_row += 1
                    else:
                        self.current_page += 1
                        self.current_row = 1 + (self.max_displayed_rows * (self.current_page - 1))
            # The up arrow key selects the previous option in the menu window and decrements the page as needed
            elif key in (66, 259, curses.KEY_UP):
                if self.current_page == 1:
                    if self.current_row > 1:
                        self.current_row -= 1
                else:
                    if self.current_row > (1 + (self.max_displayed_rows * (self.current_page - 1))):
                        self.current_row -= 1
                    else:
                        self.current_page -= 1
                        self.current_row = \
                            self.max_displayed_rows + (self.max_displayed_rows * (self.current_page - 1))
            # The page down key increments the page  and selects the row in the same position in the menu on that page
            # or the first row if the next page doesn't have an equivalent row
            # Ignore page down key presses on the last page
            elif key in (338, curses.KEY_NPAGE) and self.current_page < self.num_pages:
                self.current_page += 1
                # Bounds check to ensure there are enough items on the next page to select an item in the same position
                # This will be true for all pages but the last page which will likely be a partial page of items
                if self.current_row + self.max_displayed_rows < self.num_rows:
                    self.current_row += self.max_displayed_rows
                # If the bounds check fails then select the first item on the next (last) page
                else:
                    self.current_row = ((self.current_page - 1) * self.max_displayed_rows) + 1
            # The page up key decrements the page and selects the row in the same position in the menu on that page
            # Ignore page up key presses when on the first page
            elif key in (339, curses.KEY_PPAGE) and self.current_page > 1:
                self.current_page -= 1
                # Shift the currently selected row to the same place on the new page
                self.current_row -= self.max_displayed_rows
            elif key in (410, curses.KEY_RESIZE):
                # Get the new terminal dimensions and resize the terminal
                curses.resizeterm(*stdscr.getmaxyx())

                # Verify the terminal is still at least 80x24
                if curses.LINES < 24 or curses.COLS < 80:
                    raise curses.error(
                        "Required minimum terminal dimensions of 80x24 > {}x{}.".format(curses.COLS, curses.LINES))

                # Initialize a new WindowObject
                stdscr = curses.initscr()
                curses.noecho()
                curses.cbreak()

                main_window, screen, footer = self.draw_menu(stdscr)

                # Recalculate the current page
                # current_selected_row - 1 is needed because the row in the window is offset by 1
                self.current_page = int(math.ceil(self.current_row / self.max_displayed_rows))

                # For some reason, another getch() call is required to pull the KEY_RESIZE out of the buffer
                stdscr.getch()

            # Erase the screen so it can be cleanly redrawn
            screen.erase()
            screen.border(0)

            self._draw_menu(screen)

            # Draw the navigation items in the footer
            self._draw_footer(footer)

            # Draw the pieces of the overall screen (order matters)
            stdscr.noutrefresh()
            main_window.noutrefresh()
            screen.noutrefresh()
            footer.noutrefresh()
            curses.doupdate()