diff --git a/README.md b/README.md index d22f2a1..ac08fed 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ For more info, check out the [Wiki](https://github.com/dylanaraps/pywal/wiki). [Screenshot Examples (Reddit)](https://www.reddit.com/r/unixporn/search?q=wal&restrict_sr=on&sort=relevance&t=all) -![screenshot](https://i.imgur.com/EUdn0Kx.jpg) +![screenshot](https://i.imgur.com/aVcTPka.jpg) ## Donate diff --git a/pywal/__main__.py b/pywal/__main__.py index c59af8f..552b18b 100644 --- a/pywal/__main__.py +++ b/pywal/__main__.py @@ -10,6 +10,7 @@ Created by Dylan Araps. """ import argparse +import logging import os import shutil import sys @@ -25,7 +26,7 @@ from . import util from . import wallpaper -def get_args(args): +def get_args(): """Get the script arguments.""" description = "wal - Generate colorschemes on the fly" arg = argparse.ArgumentParser(description=description) @@ -40,10 +41,9 @@ def get_args(args): arg.add_argument("--backend", metavar="backend", help="Which color backend to use. \ Use 'wal --backend' to list backends.", - const="list_backends", type=str, - nargs="?", default="default") + const="list_backends", type=str, nargs="?") - arg.add_argument("--theme", metavar="/path/to/file or theme_name", + arg.add_argument("--theme", "-f", metavar="/path/to/file or theme_name", help="Which colorscheme file to use. \ Use 'wal --theme' to list builtin themes.", const="list_themes", nargs="?") @@ -88,24 +88,28 @@ def get_args(args): arg.add_argument("-e", action="store_true", help="Skip reloading gtk/xrdb/i3/sway/polybar") - return arg.parse_args(args) + return arg -def process_args(args): - """Process args.""" +def parse_args_exit(parser): + """Process args that exit.""" + args = parser.parse_args() + if not len(sys.argv) > 1: - print("error: wal needs to be given arguments to run.\n" - " Refer to \"wal -h\" for more info.") - sys.exit(1) - - if args.i and args.theme: - print("error: Conflicting arguments -i and -f.\n" - " Refer to \"wal -h\" for more info.") - sys.exit(1) + parser.error("wal needs to be given arguments to run.") if args.v: - print("wal", __version__) - sys.exit(0) + parser.exit(0, "wal %s\n" % __version__) + + if args.i and args.theme: + parser.error("Conflicting arguments -i and -f.") + + if not args.i and \ + not args.theme and \ + not args.R and \ + not args.backend: + parser.error("No input specified.\n" + "--backend, --theme, -i or -R are required.") if args.r: reload.colors() @@ -122,22 +126,19 @@ def process_args(args): print("Backends:", colors.list_backends()) sys.exit(0) + +def parse_args(parser): + """Process args.""" + args = parser.parse_args() + if args.q: + logging.getLogger().disabled = True sys.stdout = sys.stderr = open(os.devnull, "w") if args.c: scheme_dir = os.path.join(CACHE_DIR, "schemes") shutil.rmtree(scheme_dir, ignore_errors=True) - if args.R: - image_file = os.path.join(CACHE_DIR, "wal") - - if os.path.isfile(image_file): - args.i = util.read_file(image_file)[0] - else: - print("image: No colorscheme to restore, try 'wal -i' first.") - sys.exit(1) - if args.i: image_file = image.get(args.i) colors_plain = colors.get(image_file, args.l, args.backend) @@ -145,6 +146,9 @@ def process_args(args): if args.theme: colors_plain = theme.file(args.theme) + if args.R: + colors_plain = theme.file(os.path.join(CACHE_DIR, "colors.json")) + if args.a: util.Color.alpha_num = args.a @@ -153,15 +157,18 @@ def process_args(args): colors_plain["special"]["background"] = args.b colors_plain["colors"]["color0"] = args.b - if args.i or args.theme: - if not args.n: - wallpaper.change(colors_plain["wallpaper"]) + if not args.n: + wallpaper.change(colors_plain["wallpaper"]) - sequences.send(colors_plain, to_send=not args.s) - export.every(colors_plain) + sequences.send(colors_plain, to_send=not args.s) - if not args.e: - reload.env(tty_reload=not args.t) + if sys.stdout.isatty(): + colors.palette() + + export.every(colors_plain) + + if not args.e: + reload.env(tty_reload=not args.t) reload.external_script(args.o) @@ -173,8 +180,10 @@ def process_args(args): def main(): """Main script function.""" util.setup_logging() - args = get_args(sys.argv[1:]) - process_args(args) + parser = get_args() + + parse_args_exit(parser) + parse_args(parser) if __name__ == "__main__": diff --git a/pywal/backends/__init__.py b/pywal/backends/__init__.py index 9a116e8..192dc60 100644 --- a/pywal/backends/__init__.py +++ b/pywal/backends/__init__.py @@ -3,7 +3,7 @@ Hh ____ HP "HHF:. `._ :.,-'"" "-. F F" :::..'"" "-. `. F , \ \ "BACKENDS" -F j\ / ; `. - sorry +F j\ / ; `. | j `. ` A \ | | ;_ . 8 \ J F\_,'| "`-----.\ j `. \ diff --git a/pywal/backends/colorthief.py b/pywal/backends/colorthief.py index 7b2e2bc..bcb9e39 100644 --- a/pywal/backends/colorthief.py +++ b/pywal/backends/colorthief.py @@ -25,7 +25,7 @@ def gen_colors(img): if len(raw_colors) >= 8: break - elif i == 19: + elif i == 10: logging.error("ColorThief couldn't generate a suitable palette.") sys.exit(1) diff --git a/pywal/colors.py b/pywal/colors.py index 41b2a44..600bc21 100644 --- a/pywal/colors.py +++ b/pywal/colors.py @@ -98,6 +98,22 @@ def get_backend(backend): return backend +def palette(): + """Generate a palette from the colors.""" + col_width = " " * (os.get_terminal_size().columns // 8) + + for i in range(0, 16): + if i % 8 == 0: + print() + + if i > 7: + i = "8;5;%s" % i + + print("\033[4%sm%s\033[0m" % (i, col_width), end="") + + print("\n") + + def get(img, light=False, backend="default", cache_dir=CACHE_DIR): """Generate a palette.""" backend = get_backend(backend) @@ -112,14 +128,15 @@ def get(img, light=False, backend="default", cache_dir=CACHE_DIR): logging.info("Found cached colorscheme.") else: - logging.info("Generating a colorscheme...") + logging.info("Generating a colorscheme.") + backend = get_backend(backend) # Dynamically import the backend we want to use. # This keeps the dependencies "optional". try: - util.variable_import("pywal.backends.%s" % backend) + __import__("pywal.backends.%s" % backend) except ImportError: - util.variable_import("pywal.backends.wal") + __import__("pywal.backends.wal") backend = "wal" logging.info("Using %s backend.", backend) diff --git a/pywal/config/config.ini b/pywal/config/config.ini index 62eb4b1..dcfc20f 100644 --- a/pywal/config/config.ini +++ b/pywal/config/config.ini @@ -5,7 +5,7 @@ cmd_hook = [colors] # Color backend to use. # Possible values, see: wal --backend -backend = random +backend = [wallpaper] # Which wallpaper setter to use. diff --git a/pywal/export.py b/pywal/export.py index ed7a846..993e528 100644 --- a/pywal/export.py +++ b/pywal/export.py @@ -57,13 +57,9 @@ def every(colors, output_dir=CACHE_DIR): util.create_dir(template_dir_user) join = os.path.join # Minor optimization. - - for file in os.scandir(template_dir): - if file.name != '.DS_Store': - template(colors, file.path, join(output_dir, file.name)) - - for file in os.scandir(template_dir_user): - if file.name != '.DS_Store': + for file in [*os.scandir(template_dir), + *os.scandir(template_dir_user)]: + if file.name != ".DS_Store": template(colors, file.path, join(output_dir, file.name)) logging.info("Exported all files.") diff --git a/pywal/reload.py b/pywal/reload.py index 6bda275..a441ce7 100644 --- a/pywal/reload.py +++ b/pywal/reload.py @@ -33,12 +33,12 @@ def oomox(gen_theme): """Call oomox to generate a theme.""" if gen_theme: if not shutil.which("oomox-cli"): - logging.warning("Oomox not found, skipping...") + logging.warning("Oomox not found, skipping.") return oomox_file = os.path.join(CACHE_DIR, "colors-oomox") - logging.info("Waiting for oomox...") + logging.info("Waiting for Oomox.") subprocess.run(["oomox-cli", "-o", "wal", oomox_file], stdout=subprocess.DEVNULL) diff --git a/pywal/settings.py b/pywal/settings.py index d95b4d0..b838525 100644 --- a/pywal/settings.py +++ b/pywal/settings.py @@ -17,8 +17,8 @@ import shutil from . import util -__version__ = "1.3.3" -__cache_version__ = "1.0.0" +__version__ = "2.0.3" +__cache_version__ = "1.1.0" HOME = os.getenv("HOME", os.getenv("USERPROFILE")) diff --git a/pywal/theme.py b/pywal/theme.py index 96f86b9..c331d24 100644 --- a/pywal/theme.py +++ b/pywal/theme.py @@ -31,7 +31,7 @@ def terminal_sexy_to_wal(data): return data -def parse_theme(theme_file): +def parse(theme_file): """Parse the theme file.""" data = util.read_file_json(theme_file) @@ -70,8 +70,8 @@ def file(input_file): # Parse the theme file. if os.path.isfile(theme_file): - return parse_theme(theme_file) + return parse(theme_file) else: - logging.error("No colorscheme file found, exiting...") + logging.error("No colorscheme file found.") sys.exit(1) diff --git a/pywal/util.py b/pywal/util.py index e245404..4495dbe 100644 --- a/pywal/util.py +++ b/pywal/util.py @@ -6,6 +6,7 @@ import json import logging import os import subprocess +import sys class Color: @@ -92,17 +93,13 @@ def create_dir(directory): os.makedirs(directory, exist_ok=True) -def variable_import(module): - """Import a module dynamically.""" - __import__(module) - - def setup_logging(): """Logging config.""" logging.basicConfig(format=("[%(levelname)s\033[0m] " "\033[1;31m%(module)s\033[0m: " "%(message)s"), - level=logging.INFO) + level=logging.INFO, + stream=sys.stdout) logging.addLevelName(logging.ERROR, '\033[1;31mE') logging.addLevelName(logging.INFO, '\033[1;32mI') logging.addLevelName(logging.WARNING, '\033[1;33mW') diff --git a/tests/test_main.py b/tests/test_main.py deleted file mode 100644 index 1cc1e57..0000000 --- a/tests/test_main.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Test __main__ functions.""" -import unittest -import unittest.mock - -import os - -from pywal import __main__ -from pywal import reload -from pywal import wallpaper -from pywal import util -from pywal.settings import CACHE_DIR - - -class TestMain(unittest.TestCase): - """Test the gen_colors functions.""" - - def test_args_a(self): - """> Test arg parsing (-a).""" - args = __main__.get_args(["-a", "50"]) - __main__.process_args(args) - self.assertEqual(util.Color.alpha_num, "50") - - def test_args_c(self): - """> Test arg parsing (-c).""" - args = __main__.get_args(["-c"]) - __main__.process_args(args) - scheme_dir = os.path.join(CACHE_DIR, "schemes") - self.assertFalse(os.path.isdir(scheme_dir)) - - def test_args_e(self): - """> Test arg parsing (-e).""" - reload.env = unittest.mock.MagicMock() - args = __main__.get_args(["-e"]) - __main__.process_args(args) - self.assertFalse(reload.env.called) - - def test_args_n(self): - """> Test arg parsing (-n).""" - wallpaper.change = unittest.mock.MagicMock() - args = __main__.get_args(["-n"]) - __main__.process_args(args) - self.assertFalse(wallpaper.change.called) - - -if __name__ == "__main__": - unittest.main()