parent
c4094f6019
commit
03475d4b04
@ -0,0 +1,8 @@
|
|||||||
|
# This is mach5 config
|
||||||
|
[General]
|
||||||
|
# default_menu_file = ~/.config/mach5/menu.yml
|
||||||
|
default_menu_file = ./etc/menu.yml
|
||||||
|
|
||||||
|
# root window title and geometry
|
||||||
|
rtitle = Mach5
|
||||||
|
rgeometry = 300x600
|
@ -0,0 +1,22 @@
|
|||||||
|
name: Principal
|
||||||
|
sc: null
|
||||||
|
entries:
|
||||||
|
- cmd: gimp
|
||||||
|
name: Gimp
|
||||||
|
sc: g
|
||||||
|
- cmd: inkscape
|
||||||
|
name: Inkscape
|
||||||
|
sc: i
|
||||||
|
- name: Ideas
|
||||||
|
sc: j
|
||||||
|
entries:
|
||||||
|
- cmd: ~/apps/Treesheets/current
|
||||||
|
name: Treesheets
|
||||||
|
sc: t
|
||||||
|
- cmd: ~/apps/freeplane/current
|
||||||
|
name: Freeplane
|
||||||
|
sc: f
|
||||||
|
- name: Emacs
|
||||||
|
sc: e
|
||||||
|
cmd: emacs
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from configparser import ConfigParser, ExtendedInterpolation
|
||||||
|
import os
|
||||||
|
import errno
|
||||||
|
|
||||||
|
import machlib.menu as mm
|
||||||
|
|
||||||
|
# default_configuration_file = "~/.config/mach5/config.ini"
|
||||||
|
_default_configuration_file = "./etc/config.ini"
|
||||||
|
# _default_menu_file = "~/.config/mach5/menu.yml"
|
||||||
|
_default_menu_file = "./etc/menu.yml"
|
||||||
|
|
||||||
|
# -------------------- MAIN --------------------
|
||||||
|
|
||||||
|
# Parse command line options
|
||||||
|
arg_parser = argparse.ArgumentParser(
|
||||||
|
description='Our simple chords application')
|
||||||
|
arg_parser.add_argument('-c', '--cfg',
|
||||||
|
help='Config ini file',
|
||||||
|
default=_default_configuration_file)
|
||||||
|
arg_parser.add_argument('-m', '--menu',
|
||||||
|
help='Menu yaml file',
|
||||||
|
default=_default_menu_file)
|
||||||
|
|
||||||
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
# Load configuration file
|
||||||
|
_configuration = ConfigParser(interpolation=ExtendedInterpolation())
|
||||||
|
found = _configuration.read(os.path.expanduser(args.cfg))
|
||||||
|
|
||||||
|
if (not found):
|
||||||
|
print('[ERROR] Config file not found')
|
||||||
|
raise FileNotFoundError(errno.ENOENT,
|
||||||
|
os.strerror(errno.ENOENT), args.cfg)
|
||||||
|
|
||||||
|
menu = mm.Menu.from_file(args.menu)
|
||||||
|
|
||||||
|
print(menu)
|
||||||
|
print(menu.get_entries().keys())
|
||||||
|
for v in menu.get_entries().values():
|
||||||
|
print(f" {v}")
|
||||||
|
print(f"Len is {len(menu)}")
|
||||||
|
|
||||||
|
print ("-"*10)
|
||||||
|
for i in menu:
|
||||||
|
print(i)
|
@ -0,0 +1,119 @@
|
|||||||
|
"""Implement Mach5 menus."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import errno
|
||||||
|
import yaml
|
||||||
|
from collections import OrderedDict
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_from(menu_file):
|
||||||
|
"""Get menu data from a yaml menu definition 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)
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# WARNING #
|
||||||
|
# yaml.safe_load does NOT return and OrderedDict #
|
||||||
|
# so far, dict in Python are ordered, but IT CAN CHANGE #
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
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['sc']} 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 __repr__(self):
|
||||||
|
"""Return representation string for Command object."""
|
||||||
|
return f"{self._sc!r} - {self._name!r} - {self._cmd!r}"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""Return string conversion 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 class."""
|
||||||
|
|
||||||
|
def __init__(self, menu_data):
|
||||||
|
"""Init a menu object instance 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 __len__(self):
|
||||||
|
"""Return number of items in menu."""
|
||||||
|
return len(self._entries)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return MenuIter(self)
|
||||||
|
|
||||||
|
def from_file(path):
|
||||||
|
"""Return a Menu instance from menu definition file."""
|
||||||
|
return Menu(get_data_from(path))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
"""Return repr string for menu object."""
|
||||||
|
return f"{self._sc!r} - {self._name!r}"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
"""Return string conversion for menu."""
|
||||||
|
if self._sc:
|
||||||
|
return f"{self._sc} - {self._name}"
|
||||||
|
else:
|
||||||
|
return f"{self._name}"
|
||||||
|
|
||||||
|
def get_entries(self):
|
||||||
|
"""Return entries for menu instance."""
|
||||||
|
return self._entries
|
||||||
|
|
||||||
|
class MenuIter:
|
||||||
|
"""A helper class to make iterables Menu objects"""
|
||||||
|
|
||||||
|
def __init__(self, menu):
|
||||||
|
"""Return an iterable menu"""
|
||||||
|
self._entries = menu.get_entries()
|
||||||
|
self._current = 0
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if self._current < len(self._entries):
|
||||||
|
item = self._entries[self._current]
|
||||||
|
self._current += 1
|
||||||
|
return item
|
||||||
|
raise StopIteration
|
@ -0,0 +1 @@
|
|||||||
|
PyYAML==6.0
|
Loading…
Reference in new issue