Skip to content

Commit

Permalink
Handle actions manually instead of trying to automate them
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniosarosi committed Jan 30, 2021
1 parent 1a58c6c commit b9fc359
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 92 deletions.
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,22 +131,38 @@ If you want to apply different configs programmatically, you can either use
the CLI in a shell script or use ```pycritty``` as a python module:

```python
# Dummy script that changes the theme every 10 minutes
#!/bin/python3

# Dummy script that changes the theme every 5 minutes

from time import sleep
from pycritty.commands import ListResource, SetConfig
from pycritty.commands import Pycritty, ListResource


def main():
ls = ListResource()
conf = SetConfig()
conf = Pycritty()
while True:
for theme in ls.list_themes():
conf.change_theme(theme) # or conf.set(theme=theme)
conf.apply()
sleep(600)
sleep(300)


if __name__ == '__main__':
main()
```

Shell equivalent:

```bash
#!/bin/bash

while :; do
# Same as pycritty ls --themes --iterable
for theme in $(pycritty ls -ti); do
pycritty -t $theme
sleep 300
done
done
```
2 changes: 1 addition & 1 deletion pycritty/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Automated tools for managing alacritty configurations"""

__version__ = "0.3.2"
__version__ = "0.3.3"


class PycrittyError(Exception):
Expand Down
2 changes: 0 additions & 2 deletions pycritty/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

install_parser.add_argument(
'-o', '--override',
dest='override_config',
action='store_true',
help='Override existing config',
)
Expand All @@ -32,7 +31,6 @@

group.add_argument(
'-t', '--theme',
dest='theme',
action='store_true',
help='Install as theme',
)
Expand Down
5 changes: 2 additions & 3 deletions pycritty/cli/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
)

save_parser.add_argument(
'save_config',
'name',
metavar='NAME',
help='Name of the config being saved',
)

save_parser.add_argument(
'-o', '--override',
dest='override_config',
action='store_true',
help='Override existing config',
)
)
2 changes: 1 addition & 1 deletion pycritty/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .pycritty import SetConfig
from .pycritty import Pycritty
from .ls import ListResource
from .save import SaveConfig
from .load import LoadConfig
Expand Down
55 changes: 11 additions & 44 deletions pycritty/commands/command.py
Original file line number Diff line number Diff line change
@@ -1,51 +1,18 @@
from typing import Dict, Any
from .. import PycrittyError
from ..io import log
from abc import ABCMeta, abstractmethod


class Command:
"""Objects representing a CLI command or subcommand"""

requires_args = False
class Command(metaclass=ABCMeta):
"""Objects representing a CLI command"""

@abstractmethod
def execute(self, actions: Dict[str, Any]):
"""Execute the actions associted to this command.
By default it will try to map each action to a method
of this object and execute it with the given arguments.
>>> # Example:
>>> Command c = SomeSubclassCommand()
>>> c.execute({'do_this', [1, 2, 3], 'then_do_this', 'foo'})
>>> # Would result in:
>>> c.do_this([1, 2, 3])
>>> c.then_do_this('foo')
This makes it easier to 'reference' the code that has
to run from the CLI, but it cannot be used if the method
requires more than one argument, unless using tuples
or passing arguments manually.
"""

errors = 0
for method, args in actions.items():
call = getattr(self, method)
try:
if args is None:
call()
else:
call(args)
except PycrittyError as e:
log.err(e)
errors += 1

self.apply()

if errors > 0:
raise PycrittyError(f'\n{errors} error(s) found')

def apply(self):
"""Some commands might need to dump data to config files or run
code after all actions have been performed.
"""Actions are key value pairs parsed from sys.argv with argparse.
For example, the command that sets configs might receive this:
>>> {'set_theme': 'onedark', 'set_font': 'UbuntuMono'}
The command that installs configs might receive something like this:
>>> {'url': 'https://example.io./conf.yml', 'override': True, 'name': 'Foo'}
These key value pairs have to be interpreted as arguments or callable
functions, depending on the command.
"""
pass
11 changes: 2 additions & 9 deletions pycritty/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,10 @@ def install(
self.save.save_config(config_name, url, dest_parent, override)

def execute(self, actions: Dict[str, Any]):
if 'url' not in actions:
return

url = actions['url']
name = actions['name']
if name is None or len(name) == 0:
name = Path(urlparse(url).path).stem

override = 'override_config' in actions
dest_parent = saves_dir
if 'theme' in actions:
dest_parent = themes_dir

override = 'override' in actions
dest_parent = themes_dir if 'theme' in actions else saves_dir
self.install(name, url, dest_parent, override)
4 changes: 4 additions & 0 deletions pycritty/commands/load.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Dict, Any
from .command import Command
from .. import PycrittyError
from ..io import log, yio
Expand All @@ -17,3 +18,6 @@ def load_config(self, config_name: str):
yio.write_yaml(conf, config_file)

log.ok(f'Config "{config_name}" applied')

def execute(self, actions: Dict[str, Any]):
self.load_config(actions['load_config'])
8 changes: 4 additions & 4 deletions pycritty/commands/ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self):
self.options = {
'themes': ('Themes', log.Color.BLUE, self.list_themes),
'fonts': ('Fonts', log.Color.PURPLE, self.list_fonts),
'configs': ('Configs', log.Color.CYAN, self.list_saves),
'configs': ('Configs', log.Color.CYAN, self.list_configs),
}

def _list_dir(self, directory: Resource):
Expand All @@ -26,7 +26,7 @@ def list_themes(self) -> List[str]:

return self._list_dir(themes_dir)

def list_saves(self) -> List[str]:
def list_configs(self) -> List[str]:
if not saves_dir.exists():
raise PycrittyError(f'Cannot list saves, {saves_dir} not found')

Expand Down Expand Up @@ -59,12 +59,12 @@ def print_list(self, option: str, iterable=True):
log.color_print(f'{tabs}{item}', default_color=color)

def execute(self, args: Dict[str, Any]):
if len(args) < 1:
args['all'] = True
iterable = False
if 'iterable' in args:
iterable = True
args.pop('iterable')
if len(args) < 1:
args['all'] = True
if 'all' in args:
for opt in self.options:
args[opt] = True
Expand Down
25 changes: 21 additions & 4 deletions pycritty/commands/pycritty.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,41 @@ def __init__(self, message='Error applying configuration'):
super().__init__(message)


class SetConfig(Command):
class Pycritty(Command):
"""Applies changes to the config
>>> conf = SetConfig()
>>> conf = Pycritty()
>>> conf.change_theme('dracula')
>>> conf.change_font('UbuntuMono')
>>> conf.apply()
"""

requires_args = True

def __init__(self):
self.config = yio.read_yaml(resources.config_file.get_or_create())
if self.config is None:
self.config = {}

def apply(self):
yio.write_yaml(self.config, resources.config_file)

def execute(self, actions: Dict[str, Any]):
if len(actions) < 1:
log.warn('Nothing to do, use -h for help')
return

errors = 0
for method, args in actions.items():
call = getattr(self, method)
try:
call(args)
except PycrittyError as e:
log.err(e)
errors += 1

self.apply()

if errors > 0:
raise PycrittyError(f'\n{errors} error(s) found')

def set(self, **kwargs):
"""Set multiple changes at once
Expand Down
5 changes: 2 additions & 3 deletions pycritty/commands/rm.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ def remove(self, configs: List[str], config_parent: Resource, force=False):
file.path.unlink()

def execute(self, actions: Dict[str, Any]):
if 'configs' not in actions:
return
configs = actions['configs']
force = 'force' in actions
config_parent = themes_dir if 'theme' in actions else saves_dir
self.remove(actions['configs'], config_parent, force)
self.remove(configs, config_parent, force)
14 changes: 3 additions & 11 deletions pycritty/commands/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@


class SaveConfig(Command):
requires_args = True

def save_config(
self,
config_name: str,
Expand All @@ -32,12 +30,6 @@ def save_config(
log.ok('Config saved =>', log.Color.BLUE, dest_file)

def execute(self, actions: Dict[str, Any]):
if 'save_config' not in actions:
return

# Override config is a flag separated from the other parameters,
# in this cases it has to be treated manually
self.save_config(
config_name=actions['save_config'],
override='override_config' in actions
)
config_name = actions['name']
override = 'override' in actions
self.save_config(config_name, override=override)
9 changes: 3 additions & 6 deletions pycritty/main.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
# Pycritty
# Antonio Sarosi
# December 9, 2020
# December 2020

from . import PycrittyError
from .io import log
from .commands import subcommands, SetConfig
from .commands import subcommands, Pycritty
from .cli import parser


def main():
args = vars(parser.parse_args())
if args['subcommand'] is None:
command_receiver = SetConfig
command_receiver = Pycritty
else:
command_receiver = subcommands[args['subcommand']]
args.pop('subcommand')
if command_receiver.requires_args and len(args) < 1:
parser.print_help()
exit(0)
try:
command_receiver().execute(args)
except PycrittyError as e:
Expand Down

0 comments on commit b9fc359

Please sign in to comment.