summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--pywal/__main__.py10
-rw-r--r--pywal/export.py45
-rw-r--r--pywal/templates/colors-vscode.json14
-rw-r--r--pywal/theme.py38
-rw-r--r--pywal/util.py24
6 files changed, 121 insertions, 14 deletions
diff --git a/README.md b/README.md
index 0e14f97..443cca3 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
<img src="https://i.imgur.com/HhK3LDv.jpg" alt="img" align="right" width="400px">
-Pywal is a tool that generates a color palette from the dominant colors in an image. It then applies the colors system-wide and on-the-fly in all of your favourite programs.
+Pywal is a tool that generates a color palette from the dominant colors in an image. It then applies the colors system-wide and on-the-fly in all of your favourite programs.
There are currently 5 supported color generation backends, each providing a different palette of colors from each image. You're bound to find an appealing color-scheme.
@@ -21,4 +21,4 @@ The goal of Pywal was to be as out of the way as possible. It doesn't modify any
Terminal emulators and TTYs have their color-schemes updated in real-time with no delay. With minimal configuration this functionality can be extended to almost anything running on your system.
-### More: \[[Installation](https://github.com/dylanaraps/pywal/wiki/Installation)\] \[[Getting Started](https://github.com/dylanaraps/pywal/wiki/Getting-Started)\] \[[Customization](https://github.com/dylanaraps/pywal/wiki/Customization)\] \[[Wiki](https://github.com/dylanaraps/pywal/wiki)\] \[[Screenshots](https://www.reddit.com/r/unixporn/search?q=wal&restrict_sr=on&sort=relevance&t=all)\]
+### More: \[[Installation](https://github.com/dylanaraps/pywal/wiki/Installation)] \[[Getting Started](https://github.com/dylanaraps/pywal/wiki/Getting-Started)] \[[Customization](https://github.com/dylanaraps/pywal/wiki/Customization)] \[[Wiki](https://github.com/dylanaraps/pywal/wiki)] \[[Screenshots](https://www.reddit.com/r/unixporn/search?q=wal&restrict_sr=on&sort=relevance&t=all)]
diff --git a/pywal/__main__.py b/pywal/__main__.py
index 0f0f077..91ead11 100644
--- a/pywal/__main__.py
+++ b/pywal/__main__.py
@@ -45,7 +45,7 @@ def get_args():
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.",
+ Use 'wal --theme' to list builtin and user themes.",
const="list_themes", nargs="?")
arg.add_argument("--iterative", action="store_true",
@@ -82,6 +82,11 @@ def get_args():
arg.add_argument("-o", metavar="\"script_name\"", action="append",
help="External script to run after \"wal\".")
+ arg.add_argument("-p", metavar="\"theme_name\"",
+ help="permanently save theme to "
+ "$XDG_CONFIG_HOME/wal/colorschemes with "
+ "the specified name")
+
arg.add_argument("-q", action="store_true",
help="Quiet mode, don\'t print anything.")
@@ -192,6 +197,9 @@ def parse_args(parser):
if not args.n:
wallpaper.change(colors_plain["wallpaper"])
+ if args.p:
+ theme.save(colors_plain, args.p, args.l)
+
sequences.send(colors_plain, to_send=not args.s, vte_fix=args.vte)
if sys.stdout.isatty():
diff --git a/pywal/export.py b/pywal/export.py
index 88c98a6..0c71a76 100644
--- a/pywal/export.py
+++ b/pywal/export.py
@@ -3,22 +3,60 @@ Export colors in various formats.
"""
import logging
import os
+import re
-from .settings import CACHE_DIR, MODULE_DIR, CONF_DIR
from . import util
+from .settings import CACHE_DIR, CONF_DIR, MODULE_DIR
def template(colors, input_file, output_file=None):
"""Read template file, substitute markers and
save the file elsewhere."""
template_data = util.read_file_raw(input_file)
-
+ for i, l in enumerate(template_data):
+ for match in re.finditer(r"(?<=(?<!\{))(\{([^{}]+)\})(?=(?!\}))", l):
+ # Get the color, and the functions associated with it
+ cname, _, funcs = match.group(2).partition(".")
+ # Check that functions are needed for this color
+ if len(funcs) == 0:
+ continue
+ # Build up a string which will be replaced with the new color
+ replace_str = cname
+ # Color to be modified copied into new one
+ new_color = util.Color(colors[cname].hex_color)
+ # Execute each function to be done
+ for func in filter(None, funcs.split(")")):
+ # Get function name and arguments
+ func = func.split("(")
+ fname = func[0]
+ if fname[0] == '.':
+ fname = fname[1:]
+ if not hasattr(new_color, fname):
+ logging.error(
+ "Syntax error in template file '%s' on line '%s'",
+ input_file, i)
+ function = getattr(new_color, fname)
+
+ # If the function is callable, call it
+ if callable(function):
+ if len(func) > 1:
+ new_color = function(*func[1].split(","))
+ else:
+ new_color = function()
+ # string to replace generated colors
+ if func[0] != '.':
+ replace_str += "."
+ replace_str += "(".join(func) + ")"
+ # If the color was changed, replace with a unique identifier.
+ if new_color is not colors[cname]:
+ template_data[i] = l.replace(
+ replace_str, "color" + new_color.strip)
+ colors["color" + new_color.strip] = new_color
try:
template_data = "".join(template_data).format(**colors)
except ValueError:
logging.error("Syntax error in template file '%s'.", input_file)
return
-
util.save_file(template_data, output_file)
@@ -52,6 +90,7 @@ def get_export_type(export_type):
"speedcrunch": "colors-speedcrunch.json",
"sway": "colors-sway",
"tty": "colors-tty.sh",
+ "vscode": "colors-vscode.json",
"waybar": "colors-waybar.css",
"xresources": "colors.Xresources",
"xmonad": "colors.hs",
diff --git a/pywal/templates/colors-vscode.json b/pywal/templates/colors-vscode.json
new file mode 100644
index 0000000..0239717
--- /dev/null
+++ b/pywal/templates/colors-vscode.json
@@ -0,0 +1,14 @@
+{{
+ "editor.tokenColorCustomizations": {{
+ "functions": "{color1}",
+ "keywords": "{color2}",
+ "numbers": "{color3}",
+ "strings": "{color4}",
+ "types": "{color5}",
+ "variables": "{color6}",
+ "comments": "{color8}"
+ }},
+ "workbench.colorCustomizations": {{
+ "editor.background": "{background}"
+ }}
+}}
diff --git a/pywal/theme.py b/pywal/theme.py
index fcd1dd1..9dc4f13 100644
--- a/pywal/theme.py
+++ b/pywal/theme.py
@@ -6,7 +6,7 @@ import os
import random
import sys
-from .settings import CONF_DIR, MODULE_DIR
+from .settings import CACHE_DIR, CONF_DIR, MODULE_DIR
from . import util
@@ -19,20 +19,30 @@ def list_out():
user_themes = [theme.name.replace(".json", "")
for theme in list_themes_user()]
+ try:
+ last_used_theme = util.read_file(os.path.join(
+ CACHE_DIR, "last_used_theme"))[0].replace(".json", "")
+ except FileNotFoundError:
+ last_used_theme = ""
+
if user_themes:
print("\033[1;32mUser Themes\033[0m:")
- print(" -", "\n - ".join(sorted(user_themes)))
+ print(" -", "\n - ".join(t + " (last used)" if t == last_used_theme
+ else t for t in sorted(user_themes)))
print("\033[1;32mDark Themes\033[0m:")
- print(" -", "\n - ".join(sorted(dark_themes)))
+ print(" -", "\n - ".join(t + " (last used)" if t == last_used_theme else t
+ for t in sorted(dark_themes)))
print("\033[1;32mLight Themes\033[0m:")
- print(" -", "\n - ".join(sorted(ligh_themes)))
+ print(" -", "\n - ".join(t + " (last used)" if t == last_used_theme else t
+ for t in sorted(ligh_themes)))
print("\033[1;32mExtra\033[0m:")
print(" - random (select a random dark theme)")
print(" - random_dark (select a random dark theme)")
print(" - random_light (select a random light theme)")
+ print(" - random_user (select a random user theme)")
def list_themes(dark=True):
@@ -88,6 +98,13 @@ def get_random_theme(dark=True):
return themes[0]
+def get_random_theme_user():
+ """Get a random theme file from user theme directories."""
+ themes = [theme.path for theme in list_themes_user()]
+ random.shuffle(themes)
+ return themes[0]
+
+
def file(input_file, light=False):
"""Import colorscheme from json file."""
util.create_dir(os.path.join(CONF_DIR, "colorschemes/light/"))
@@ -106,6 +123,9 @@ def file(input_file, light=False):
elif input_file == "random_light":
theme_file = get_random_theme(light)
+ elif input_file == "random_user":
+ theme_file = get_random_theme_user()
+
elif os.path.isfile(user_theme_file):
theme_file = user_theme_file
@@ -116,9 +136,19 @@ def file(input_file, light=False):
if os.path.isfile(theme_file):
logging.info("Set theme to \033[1;37m%s\033[0m.",
os.path.basename(theme_file))
+ util.save_file(os.path.basename(theme_file),
+ os.path.join(CACHE_DIR, "last_used_theme"))
return parse(theme_file)
logging.error("No %s colorscheme file found.", bri)
logging.error("Try adding '-l' to set light themes.")
logging.error("Try removing '-l' to set dark themes.")
sys.exit(1)
+
+
+def save(colors, theme_name, light=False):
+ """Save colors to a theme file."""
+ theme_file = theme_name + ".json"
+ theme_path = os.path.join(CONF_DIR, "colorschemes",
+ "light" if light else "dark", theme_file)
+ util.save_file_json(colors, theme_path)
diff --git a/pywal/util.py b/pywal/util.py
index e4b146a..cd6628a 100644
--- a/pywal/util.py
+++ b/pywal/util.py
@@ -5,10 +5,11 @@ import colorsys
import json
import logging
import os
+import platform
+import re
import shutil
import subprocess
import sys
-import platform
class Color:
@@ -35,7 +36,7 @@ class Color:
def rgba(self):
"""Convert a hex color to rgba."""
return "rgba(%s,%s,%s,%s)" % (*hex_to_rgb(self.hex_color),
- int(self.alpha_num)/100)
+ int(self.alpha_num) / 100)
@property
def alpha(self):
@@ -57,6 +58,21 @@ class Color:
"""Strip '#' from color."""
return self.hex_color[1:]
+ def lighten(self, percent):
+ """Lighten color by percent"""
+ percent = float(re.sub(r'[\D\.]', '', str(percent)))
+ return Color(lighten_color(self.hex_color, percent / 100))
+
+ def darken(self, percent):
+ """Darken color by percent"""
+ percent = float(re.sub(r'[\D\.]', '', str(percent)))
+ return Color(darken_color(self.hex_color, percent / 100))
+
+ def saturate(self, percent):
+ """Saturate a color"""
+ percent = float(re.sub(r'[\D\.]', '', str(percent)))
+ return Color(saturate_color(self.hex_color, percent / 100))
+
def read_file(input_file):
"""Read data from a file and trim newlines."""
@@ -156,11 +172,11 @@ def blend_color(color, color2):
def saturate_color(color, amount):
"""Saturate a hex color."""
r, g, b = hex_to_rgb(color)
- r, g, b = [x/255.0 for x in (r, g, b)]
+ r, g, b = [x / 255.0 for x in (r, g, b)]
h, l, s = colorsys.rgb_to_hls(r, g, b)
s = amount
r, g, b = colorsys.hls_to_rgb(h, l, s)
- r, g, b = [x*255.0 for x in (r, g, b)]
+ r, g, b = [x * 255.0 for x in (r, g, b)]
return rgb_to_hex((int(r), int(g), int(b)))