jwlodek / py_cui

A python library for intuitively creating CUI/TUI interfaces with widgets, inspired by gocui.
https://jwlodek.github.io/py_cui-docs
BSD 3-Clause "New" or "Revised" License
752 stars 42 forks source link

[notabug][helpwanted] Not sure how popup is meant to work ? #183

Open stuaxo opened 1 year ago

stuaxo commented 1 year ago

I'm making a menu that, ideally would display on the existing terminal output, without the "root" window, it also has key shortcuts for each item.

I tried using add_popup, but on my first try:

In the end, I've used a normal menu, it's not ideal, as the background is there and it's possible to focus the root element.

(My use-case for the hotkeys is a scenario where the screen is sometimes blank).

Here's the for a menu of options code so far - are there some really obvious things I'm missing ?

import re
import sys

import py_cui
from py_cui.keys import get_ascii_from_char

class SimplishMenu:
    # Match any keys in square brackets:
    HOTKEY_REGEX = r'\[(.*?)\]'

    def __init__(self, title, items, row=0, column=0, root=None):
        if root is None:
            root = py_cui.PyCUI(30, 30)

        items = list(items)
        row_span = len(items)
        column_span = max(len(item) for item in items)

        self.menu = root.add_scroll_menu(title, row, column, row_span + 1, column_span)
        self.menu.add_key_command(py_cui.keys.KEY_ENTER, lambda: self.choose_item(self.menu.get()))

        # Hotkeys
        self.menu.add_text_color_rule(self.HOTKEY_REGEX, py_cui.RED_ON_BLACK, 'contains', match_type='regex')
        for item in items:
            self.add_item(item)
        self.root = root
        self.root.move_focus(self.menu)

    def choose_item(self, item):
        if self.menu.get() != item:
            # If item was chosen via hotkey, select it
            self.menu.set_selected_item(item)

        self.root.stop()

    def add_item(self, item):
        hotkeys = ''.join(re.findall(self.HOTKEY_REGEX, item))
        if hotkeys:
            for hotkey in hotkeys.lower():
                self.menu.add_key_command(get_ascii_from_char(hotkey), lambda: self.choose_item(item))
        self.menu.add_item(item)

    def get(self):
        return self.menu.get()

    def show(self):
        self.root.move_focus(self.menu)
        self.root.start()

def choose_option(title, items):
    root = py_cui.PyCUI(10, 10, auto_focus_buttons=True, exit_key=None)
    menu = SimplishMenu(title, items, root=root)
    root.start()
    return menu.get()

if __name__ == '__main__':
    option = choose_option('Main Menu', ['Option [1]', 'Option [2]'])
    print("Chose: ", option)
jwlodek commented 1 year ago

Could you post the code where you tried to use the add_popup mechanism?

You can get a reference to the active popup using the root element:

root._popup

When there isn't an active one, this will be set to None. The current logic doesn't really support adding hotkeys to popups, although that shouldn't be too challenging to add if it is a worthwhile feature.