Menus with curses in python
import curses | |
class Menu: | |
def __init__(self, y, x, options): | |
self.y = y | |
self.x = x | |
self.options = options | |
self.height = len(options) | |
self.width = max(len(opt) for opt in options) | |
self.win = curses.newwin(self.height + 2, self.width + 8, y, x) | |
self.sel = 0 | |
self.optfmt = f' | {{:<{self.width}s}} | ' | |
def draw(self): | |
self.win.addstr(0, 0, ' /--' + '-' * self.width + '--\\ ') | |
for i, opt in enumerate(self.options): | |
self.win.addstr(i + 1, 0, self.optfmt.format(opt)) | |
self.win.addstr(self.height + 1, 0, ' \\--' + '-' * self.width + '--/') | |
self.win.addstr(self.sel + 1, 0, '==> ') | |
def setsel(self, n): | |
self.win.addstr(self.sel + 1, 0, ' | ') | |
self.sel = n | |
self.win.addstr(self.sel + 1, 0, '==> ') | |
def getsel(self): | |
while (key := self.win.getkey()) not in ('f', '\n'): | |
if key == 'k': | |
self.setsel((self.sel - 1) % self.height) | |
self.win.refresh() | |
if key == 'j': | |
self.setsel((self.sel + 1) % self.height) | |
self.win.refresh() | |
if key == 'a': | |
return None | |
return self.options[self.sel] | |
def refresh(self): | |
return self.win.refresh() | |
def clear(self): | |
return self.win.clear() | |
def tree_menu_sel(y, x, options_tree): | |
def get_title(opt): | |
if isinstance(opt, str): | |
return opt | |
else: | |
return opt[0] | |
m = Menu(y, x, [get_title(opt) for opt in options_tree]) | |
m.draw() | |
m.refresh() | |
while True: | |
sel = m.getsel() | |
if sel is None: | |
m.clear() | |
m.refresh() | |
return None | |
for i, optx in enumerate(options_tree): | |
if isinstance(optx, str): | |
title = optx | |
subtree = None | |
else: | |
title, subtree = optx | |
if sel == title: | |
if not subtree: | |
return sel, | |
else: | |
r = tree_menu_sel(y + i, x + m.width + 5, subtree) | |
if r: | |
return (sel,) + r | |
else: | |
m.draw() | |
m.refresh() | |
break | |
def main(stdscr): | |
curses.curs_set(False) | |
stdscr.clear() | |
stdscr.addstr("Hello!") | |
stdscr.refresh() | |
# m = Menu(7, 20, ("Say hello", "Say goodbye", "Exit")) | |
# m.draw() | |
# m.refresh() | |
# sel = m.getsel() | |
sel = tree_menu_sel(7, 20, (("Say hello", | |
("To Alice", "To Bob")), | |
("Say goodbye", | |
("Loudly", | |
("Quietly", | |
("To Alice", "To Bob")))), | |
"Exit")) | |
stdscr.addstr("\n" + " > ".join(sel)) | |
stdscr.getkey() | |
if __name__ == '__main__': | |
curses.wrapper(main) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment