You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.6 KiB

"""Implements Mach5 menues."""
import os.path
import errno
import yaml
from collections import OrderedDict
from getkey import getkey, keys
import subprocess
import tkinter as tk
def get_data_from(menu_file):
"""Get menu data from a yaml menu file."""
menu_file = os.path.expanduser(menu_file)
if not os.path.exists(menu_file):
raise FileNotFoundError(errno.ENOENT,
os.strerror(errno.ENOENT), menu_file)
with open(menu_file, 'r') as yaml_file:
menu_data = yaml.safe_load(yaml_file)
if 'entries' not in menu_data:
raise ValueError(f"Malformed file {menu_file}.\
First entry is not a menu")
return(menu_data)
class Command:
"""A Mach5 command."""
def __init__(self, cmd_data):
"""Construct a Mach5 command object."""
if len(cmd_data['sc']) != 1:
raise ValueError(f"Shortcut must be only one character.\
{cmd_data['heu']} is invalid.")
self._name = cmd_data['name']
self._cmd = cmd_data['cmd']
self._sc = cmd_data['sc']
def show(self):
"""Return string for Command."""
return f"{self._sc} - {self._name}"
def execute(self):
"""Execute command."""
print(f"Execute command {self._name}")
subprocess.Popen(os.path.expanduser(self._cmd))
class Menu:
"""A Mach5 menu."""
def __init__(self, menu_data):
"""Construct a menu object from a menu data dict."""
self._name = menu_data['name']
self._entries = OrderedDict()
self._sc = menu_data['sc']
for e in menu_data['entries']:
if e['sc'] in self._entries:
raise ValueError(f"Repeated shortcut {e['sc']}")
if 'entries' in e:
self._entries[e['sc']] = Menu(e)
else:
self._entries[e['sc']] = Command(e)
def show(self, recursive=False):
"""Show Menu."""
my_str = ""
if self._sc:
my_str = f"{self._sc} - "
my_str += f"{self._name} (m)"
if recursive:
my_str += "\n"
for i, v in self._entries.items():
my_str += f"{v.show()}\n"
return my_str
def show_entries(self):
"""Show Menu entries."""
my_str = ''
for i, v in self._entries.items():
my_str += f"{v.show()}\n"
return my_str
def get_command(self):
"""Get command from menu."""
print(self.show(True))
while True:
opt = getkey()
if opt in self._entries:
if isinstance(self._entries[opt], Menu):
return self._entries[opt].get_command()
else:
return self._entries[opt]
elif opt == keys.ESC:
exit(0)
def get_option(self):
"""Get option with Tkinter."""
def key_pressed(event):
"""Return char for key_pressed event."""
opt = event.char
if opt in self._entries:
if isinstance(self._entries[opt], Menu):
return self._entries[opt].get_option()
else:
root.destroy()
self._entries[opt].execute()
exit(0)
elif opt == keys.ESC:
exit(0)
root = tk.Tk()
root.geometry('300x100')
root.title("Mach5")
text_box = tk.Text(root)
text_box.insert(tk.END, self.show(True))
text_box.grid(row=0, column=0)
root.bind("<Any-KeyPress>", key_pressed)
root.mainloop()