Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a 'theme' command #1603

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions alot/commands/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from ..settings.const import settings
from ..settings.errors import ConfigError, NoMatchingAccount
from ..utils import argparse as cargparse
from ..settings.theme import Theme

MODE = 'global'

Expand Down Expand Up @@ -1088,6 +1089,42 @@ def apply(self, ui):
ui.notify('Error when reloading config files:\n {}'.format(e),
priority='error')

@registerCommand(MODE, 'theme', arguments=[
(['theme_name'], {'help': 'Name of the theme'})], help='Select your own them')
class ThemeCommand(Command):

"""move in widget"""
def __init__(self, theme_name=None, **kwargs):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not do anything so could be omitted? the docstring is also not correct is it?

self.theme = theme_name
# if movement is None:
# self.movement = ''
# else:
# self.movement = ' '.join(movement)
Command.__init__(self, **kwargs)

"""Reload configuration."""
def apply(self, ui):
# theme = matt

try:
themes_dir = settings._config.get('themes_dir')

theme_path = Theme.find(self.theme, themes_dir)
if theme_path is None:
# theme.find_theme()
raise ConfigError('Could not find theme {}, see log for more '
'information'.format(self.theme))

settings._theme = Theme(theme_path)
logging.info("Applied theme %s", theme_path)
ui.current_buffer.rebuild()

ui.update()

except ConfigError as e:
ui.notify('Error when loading theme:\n {}'.format(e),
priority='error')


@registerCommand(
MODE, 'savequery',
Expand Down
9 changes: 8 additions & 1 deletion alot/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import urwid
import magic


def split_commandline(s):
"""
splits semi-colon separated commandlines, ignoring quoted separators
Expand Down Expand Up @@ -616,3 +615,11 @@ def get_notmuch_config_path():
if profile:
profile = '.' + profile
return os.path.expanduser('~/.notmuch-config' + profile)

# DATA_DIRS = get_xdg_env('XDG_DATA_DIRS',
# '/usr/local/share:/usr/share').split(':')

def get_xdg_data_dirs():
return get_xdg_env('XDG_DATA_DIRS',
'/usr/local/share:/usr/share').split(':')

35 changes: 11 additions & 24 deletions alot/settings/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from ..account import SendmailAccount
from ..addressbook.abook import AbookAddressBook
from ..addressbook.external import ExternalAddressbook
from ..helper import pretty_datetime, string_decode, get_xdg_env
from ..helper import pretty_datetime, string_decode, get_xdg_env, get_xdg_data_dirs
from ..utils import configobj as checks

from .errors import ConfigError, NoMatchingAccount
Expand All @@ -23,8 +23,6 @@


DEFAULTSPATH = os.path.join(os.path.dirname(__file__), '..', 'defaults')
DATA_DIRS = get_xdg_env('XDG_DATA_DIRS',
'/usr/local/share:/usr/share').split(':')


class SettingsManager:
Expand Down Expand Up @@ -96,28 +94,17 @@ def read_config(self, path):
logging.debug('themes directory: `%s`' % themes_dir)

# if config contains theme string use that
data_dirs = [os.path.join(d, 'alot/themes') for d in DATA_DIRS]
if themestring:
# This is a python for/else loop
# https://docs.python.org/3/reference/compound_stmts.html#for
#
# tl/dr; If the loop loads a theme it breaks. If it doesn't break,
# then it raises a ConfigError.
for dir_ in itertools.chain([themes_dir], data_dirs):
theme_path = os.path.join(dir_, themestring)
if not os.path.exists(os.path.expanduser(theme_path)):
logging.warning('Theme `%s` does not exist.', theme_path)
else:
try:
self._theme = Theme(theme_path)
except ConfigError as e:
raise ConfigError('Theme file `%s` failed '
'validation:\n%s' % (theme_path, e))
else:
break
else:
raise ConfigError('Could not find theme {}, see log for more '
'information'.format(themestring))
try:
theme_path = Theme.find(themestring, themes_dir)
self._theme = Theme(theme_path)
except ConfigError as e:
raise ConfigError('Theme file `%s` failed '
'validation:\n%s' % (path, e))

# else:
# raise ConfigError('Could not find theme {}, see log for more '
# 'information'.format(themestring))

# if still no theme is set, resort to default
if self._theme is None:
Expand Down
39 changes: 39 additions & 0 deletions alot/settings/theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
# This file is released under the GNU GPL, version 3 or a later revision.
# For further details see the COPYING file
import os
import logging
import itertools

from ..utils import configobj as checks
from .utils import read_config
from .errors import ConfigError
from ..helper import get_xdg_data_dirs

DEFAULTSPATH = os.path.join(os.path.dirname(__file__), '..', 'defaults')
DUMMYDEFAULT = ('default',) * 6

# TODO share this one from utils maybe ?


class Theme:
"""Colour theme"""
Expand All @@ -20,11 +25,45 @@ def __init__(self, path):
:raises: :class:`~alot.settings.errors.ConfigError`
"""
self._spec = os.path.join(DEFAULTSPATH, 'theme.spec')
logging.debug("Loading theme spec %s", self._spec)

self._colours = [1, 16, 256]

# path = self.find(theme_name)
# if path is not None:
# return Theme(theme_path)
self._load_theme(path)
# else:
# raise ConfigError('Could not find theme {}, see log for more '
# 'information'.format(theme_name))


"""Returns (Boolean, abspath)"""
@staticmethod
# def exists(themestring):
def find(themestring: str, themes_dir=None):
# This is a python for/else loop
# https://docs.python.org/3/reference/compound_stmts.html#for
#
# tl/dr; If the loop loads a theme it breaks. If it doesn't break,
# then it raises a ConfigError.

data_dirs = [os.path.join(d, 'alot/themes') for d in get_xdg_data_dirs()]

for dir_ in itertools.chain([themes_dir] if themes_dir else [], data_dirs):
theme_path = os.path.join(dir_, themestring)
if not os.path.exists(os.path.expanduser(theme_path)):
logging.warning('Theme `%s` does not exist.', theme_path)
else:
return theme_path

def _load_theme(self, path):
self._config = read_config(path, self._spec, report_extra=True,
checks={'align': checks.align_mode,
'widthtuple': checks.width_tuple,
'force_list': checks.force_list,
'attrtriple': checks.attr_triple})
logging.info("TOTO", self._config)
self._colours = [1, 16, 256]
# make sure every entry in 'order' lists have their own subsections
threadline = self._config['search']['threadline']
Expand Down
10 changes: 6 additions & 4 deletions alot/settings/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ def read_config(configpath=None, specpath=None, checks=None,

try:
config = ConfigObj(infile=configpath, configspec=specpath,
file_error=True, encoding='UTF8')
raise_errors = True,
file_error=True, encoding='UTF8')
except ConfigObjError as e:
msg = 'Error when parsing `%s`:\n%s' % (configpath, e)
logging.error(msg)
raise ConfigError(msg)
except IOError:
raise ConfigError('Could not read %s and/or %s'
% (configpath, specpath))
except IOError as e:
raise e
# print(e)
# raise ConfigError('Could not read %s and/or %s' % (configpath, specpath))
except UnboundLocalError:
# this works around a bug in configobj
msg = '%s is malformed. Check for sections without parents..'
Expand Down