我之前再我的程序里面 用了一个第三方库:
simple_term_menu
,提供菜单功能。但是当我再windows上尝试跑一下终于写好的程序时,竟然不能用。原因是它依赖于termios
库, 不支持 win 。 因为我的功能需求比较简单,我决定自己下一个代替品,就是这个dumb_meun
了。
主要要实现的功能:
- 传入一个 list ,显示菜单, 返回选中的 index
- 上下键选择
- enter建确认
- *支持快捷键
因为python没有提供类似于c语言中的getchar
函数,再 linux 上用 termios
库可以实现,但是在windows上使用的是 msvcrt
库。所以实际上在 python 中实现起来不是很容易。
1def get_key(): #get keypress using getch , msvcrt = windows or termios = linux
2 try :
3 import getch
4 first_char = getch.getch()
5 if first_char == '\x1b': #arrow keys
6 a=getch.getch()
7 b=getch.getch()
8 return {'[A': 'up', '[B': 'down', '[C': 'right', '[D': 'left' }[a+b]
9 if ord(first_char) == 10:
10 return 'enter'
11 if ord(first_char) == 32:
12 return 'space'
13 else:
14 return first_char #normal keys like abcd 1234
15 except :
16 pass
17 try:
18 import msvcrt
19 key = msvcrt.getch() # get keypress
20 if key == b'\x1b': # Esc key to exit
21 return 'esc'
22 elif key == b'\r': # Enter key to select
23 return 'enter'
24 elif key == b'\x48': # Up or Down arrow
25 return 'up'
26 elif key == b'\x50': # Up or Down arrow
27 return 'down'
28 else:
29 return key.decode('utf-8')
30 except:
31 pass
32
33while True:
34 key = get_key()
35 print("You pressed: ", key)
这个函数可以获取键盘输入,返回值是一个字符串,比如up
down
/ enter
/ a
b
c
/ 1
2
3
,这样统一一下,可以兼容linux 和 win。
测试结果:
1Press a key to test out!
2You pressed: down
3You pressed: up
4You pressed: a
5...
menu代码
我拷问了chatgpt老半天,他才给我编好
-
提取快捷键是用
re
库的正则表达式 -
显示菜单通过
os.system("cls" if os.name == "nt" else "clear")
清屏,再打印出来,每次给菜单传入 list 和选中的 index ,这样用户可以看到自己正在选择哪个。
1import os
2import re
3def get_menu_choice(options):
4 shortcuts = scan_short_cuts(options) # scan for shortcuts
5 selected_index = 0
6 print(shortcuts)
7 while True:
8 show_menu(options, selected_index)
9 key = get_key()
10 if key == 'enter': # Enter key to select
11 return selected_index
12 elif key in ('up','down'): # Up or Down arrow
13 selected_index = (selected_index + (1 if key == 'down' else -1) + len(options)) % len(options)
14 elif key in shortcuts: # Shortcut key
15 show_menu(options, shortcuts[key]) #show selected option when using shortcut
16 return shortcuts[key]
17
18def scan_short_cuts(options):
19 shortcuts = {}
20 for i, option in enumerate(options):
21 match = re.match(r"\[(.*)\](.*)", option)
22 if match:
23 shortcut, text = match.group(1, 2)
24 shortcuts[shortcut] = i
25 return shortcuts
26
27
28def show_menu(options, selected_index):
29 os.system("cls" if os.name == "nt" else "clear")
30 print("Menu","current option:",selected_index)
31 for i, option in enumerate(options):
32 if i == selected_index:
33 print(f"> {option}")
34 else:
35 print(f" {option}")
36 print("\nUse the arrow keys to move, Enter/Hotkey to select.")
使用方法非常直白:
1options = ["[1]Option 1", "[2]Option 2", "[3]Option 3","[q]quit"]
2index = get_menu_choice(options)
3print(f"You selected option {index + 1}: {options[index]}")
看看效果:
代码地址
其实我一开始想要参考一下
simple_term_menu
的源码,但是我发现我太菜了,根本看不懂他们的贼复杂的源代码(还用了信号啥的,我都不会),所以我就自己写了一个简单的。
使用的话就:
1pip install dumb-menu
可以看看我在 pypi 写的简明教程