mirror of
https://github.com/avatao-content/baseimage-tutorial-framework
synced 2024-11-15 09:17:17 +00:00
69 lines
2.5 KiB
Python
69 lines
2.5 KiB
Python
import logging
|
|
from abc import ABC
|
|
from re import match
|
|
from shlex import split
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class TerminalCommands(ABC):
|
|
# pylint: disable=anomalous-backslash-in-string
|
|
"""
|
|
A class you can use to define hooks for terminal commands. This means that you can
|
|
have python code executed when the user enters a specific command to the terminal on
|
|
our frontend.
|
|
|
|
To receive events you need to subscribe TerminalCommand.callback to a HistoryMonitor
|
|
instance.
|
|
|
|
Inherit from this class and define methods which start with "command\_". When the user
|
|
executes the command specified after the underscore, your method will be invoked. All
|
|
such commands must expect the parameter \*args which will contain the arguments of the
|
|
command.
|
|
|
|
For example to define a method that runs when someone starts vim in the terminal
|
|
you have to define a method like: "def command_vim(self, \*args)"
|
|
|
|
You can also use this class to create new commands similarly.
|
|
"""
|
|
def __init__(self, bashrc):
|
|
self._command_method_regex = r'^command_(.+)$'
|
|
self.command_implemetations = self._build_command_to_implementation_dict()
|
|
if bashrc is not None:
|
|
self._setup_bashrc_aliases(bashrc)
|
|
|
|
def _build_command_to_implementation_dict(self):
|
|
return {
|
|
self._parse_command_name(fun): getattr(self, fun)
|
|
for fun in dir(self)
|
|
if callable(getattr(self, fun))
|
|
and self._is_command_implementation(fun)
|
|
}
|
|
|
|
def _setup_bashrc_aliases(self, bashrc):
|
|
with open(bashrc, 'a') as ofile:
|
|
alias_template = 'type {0} &> /dev/null || alias {0}="{0} &> /dev/null"\n'
|
|
for command in self.command_implemetations.keys():
|
|
ofile.write(alias_template.format(command))
|
|
|
|
def _is_command_implementation(self, method_name):
|
|
return bool(self._match_command_regex(method_name))
|
|
|
|
def _parse_command_name(self, method_name):
|
|
try:
|
|
return self._match_command_regex(method_name).groups()[0]
|
|
except AttributeError:
|
|
return ''
|
|
|
|
def _match_command_regex(self, string):
|
|
return match(self._command_method_regex, string)
|
|
|
|
def callback(self, command):
|
|
parts = split(command)
|
|
command = parts[0]
|
|
if command in self.command_implemetations.keys():
|
|
try:
|
|
self.command_implemetations[command](*parts[1:])
|
|
except Exception: # pylint: disable=broad-except
|
|
LOG.exception('Command "%s" failed:', command)
|