-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCursesMenu.py
108 lines (87 loc) · 3.72 KB
/
CursesMenu.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import curses
import sys
import os
class CursesMenu(object):
INIT = {'type' : 'init'}
def __init__(self, menu_options):
self.screen = curses.initscr()
self.menu_options = menu_options
self.selected_option = 0
self._previously_selected_option = None
self.running = True
#init curses and curses input
curses.noecho()
curses.cbreak()
curses.start_color()
curses.curs_set(0) #Hide cursor
self.screen.keypad(1)
self.screen.erase()
#set up color pair for highlighted option
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
self.hilite_color = curses.color_pair(1)
self.normal_color = curses.A_NORMAL
def prompt_selection(self, parent=None):
if parent is None:
lastoption = "Exit"
else:
lastoption = "Return to previous menu ({})".format(parent['title'])
option_count = len(self.menu_options['options'])
input_key = None
ENTER_KEY = ord('\n')
while input_key != ENTER_KEY:
if self.selected_option != self._previously_selected_option:
self._previously_selected_option = self.selected_option
self.screen.border(0)
self._draw_title()
for option in range(option_count):
if self.selected_option == option:
self._draw_option(option, self.hilite_color)
else:
self._draw_option(option, self.normal_color)
if self.selected_option == option_count:
self.screen.addstr(5 + option_count, 4, "{:2} - {}".format(option_count+1,
lastoption), self.hilite_color)
else:
self.screen.addstr(5 + option_count, 4, "{:2} - {}".format(option_count+1,
lastoption), self.normal_color)
max_y, max_x = self.screen.getmaxyx()
if input_key is not None:
self.screen.addstr(max_y-3, max_x - 5, "{:3}".format(self.selected_option))
self.screen.refresh()
input_key = self.screen.getch()
down_keys = [curses.KEY_DOWN, ord('j')]
up_keys = [curses.KEY_UP, ord('k')]
exit_keys = [ord('q')]
if input_key in down_keys:
if self.selected_option < option_count:
self.selected_option += 1
else:
self.selected_option = 0
if input_key in up_keys:
if self.selected_option > 0:
self.selected_option -= 1
else:
self.selected_option = option_count
if input_key in exit_keys:
self.selected_option = option_count #auto select exit and return
break
return self.selected_option
def _draw_option(self, option_number, style):
self.screen.addstr(5 + option_number,
4,
"{:2} - {}".format(option_number+1, self.menu_options['options'][option_number]['title']),
style)
def _draw_title(self):
self.screen.addstr(2, 2, self.menu_options['title'], curses.A_STANDOUT)
self.screen.addstr(4, 2, self.menu_options['subtitle'], curses.A_BOLD)
def display(self):
selected_option = self.prompt_selection()
i, _ = self.screen.getmaxyx()
curses.endwin()
os.system('clear')
if selected_option < len(self.menu_options['options']):
selected_opt = self.menu_options['options'][selected_option]
return selected_opt
else:
self.running = False
return {'title' : 'Exit', 'type' : 'exitmenu'}