best practice for invoking menu cmds
dcsan opened this issue · comments
sorry for using your issues as a discussion board but ...
how do you recommend invoking a menu command? I'm doing something like below, not sure if it's very pythonic, or if it might be worth adding to the core library a way to associate menu options with their functions.
# cmdname, function-ptr
menu_opts = {
'timeslice': timeslice,
'webapp': webapp,
'split_sessions': split_sessions,
'quit': quit
}
def run_cmd(opt):
"""exec related anon func"""
# print('menu_opts', menu_opts)
cmd = menu_opts[opt]
cmd()
No worries.
There was another library out there that explicitly did this behavior - paired menu options to functions, and invoked the functions, but at the time I wrote this lib, I wanted something simpler, that would allow you to do the same thing with little fuss, but would also allow you to just access the raw menu option chosen, if you wanted that.
I got an email with what must've been your first draft of this issue, that also included some CLI input... I've used pimento
like this myself, and this is what I've done:
def run():
menu_opts = ...
choices = menu_opts.keys()
user_choice = get_from_args(choices) or get_from_menu(choices)
menu_opts[user_choice]()
...where get_from_args
gets the choice from the CLI invocation arguments, if any, otherwise returns something falsey like None
, and get_from_menu
uses pimento to present a menu and return the option.
For more complex CLI's with lots of arguments, I will generally tell a user in the help text that an argument is required, check if it was set, and then if not, present a menu.
In other cases I prefer something like dispatcher(get_from_menu(options))
, because it's cleaner at the caller level than what the above boils down to (menu_opts[get_from_menu(menu_opts.keys())]()
), and inside dispatcher
you can call functions that take arguments, further parse the menu choice, etc. Depends on what you need and personal preferences at that point, though, I think.
One of the big things I cared about when I wrote this lib, though, was that you don't always want to run a function when you present a menu. A menu presented for "choose a color" is just going to pass that color into another function - it's not going to call a do_it_with_red
or do_it_with_blue
function, it's just going to call do_it(color=chosen_color)
.
So I wanted a menu that would just return a choice to me, and I'm probably going to keep it that way.
Although... I could see adding a few more functions to the top level API, like dispatch_menu
or dict_menu
that just wrapped some of these calls up. I admit your use case is common (like I said, I've done it several times, too), so I could see adding a new function to make it simpler.
while formalizing the data structs, a way to have simple menu numbers,
and allow one-key choice of them (without return) would be good.
1 tex
2 rugs
3 socks
could you make this a separate issue? Also, what about lists longer than 9 items? to allow choice without hitting enter requires unique input - would you want leading 0's 000 - 999
, or just disallow the non-return selection for longer lists?
new ticket made.