General: Split wal into multiple files.

This commit is contained in:
Dylan Araps 2017-06-26 12:09:35 +10:00
parent d17282cdc0
commit 583a0c19ad
9 changed files with 599 additions and 588 deletions

View File

@ -2,7 +2,111 @@
wal - Generate and change colorschemes on the fly. wal - Generate and change colorschemes on the fly.
Created by Dylan Araps. Created by Dylan Araps.
""" """
from pywal.wal import main import argparse
import os
import shutil
import sys
from pywal import settings as s
from pywal import export
from pywal import gen_colors
from pywal import set_colors
from pywal import wallpaper
from pywal import util
__version__ = "0.1.6"
def get_args():
"""Get the script arguments."""
description = "wal - Generate colorschemes on the fly"
arg = argparse.ArgumentParser(description=description)
# Add the args.
arg.add_argument("-c", action="store_true",
help="Delete all cached colorschemes.")
arg.add_argument("-i", metavar="\"/path/to/img.jpg\"",
help="Which image or directory to use.")
arg.add_argument("-n", action="store_true",
help="Skip setting the wallpaper.")
arg.add_argument("-o", metavar="\"script_name\"",
help="External script to run after \"wal\".")
arg.add_argument("-q", action="store_true",
help="Quiet mode, don\"t print anything and \
don't display notifications.")
arg.add_argument("-r", action="store_true",
help="Reload current colorscheme.")
arg.add_argument("-t", action="store_true",
help="Fix artifacts in VTE Terminals. \
(Termite, xfce4-terminal)")
arg.add_argument("-v", action="store_true",
help="Print \"wal\" version.")
return arg.parse_args()
def process_args(args):
"""Process args."""
# If no args were passed.
if not len(sys.argv) > 1:
print("error: wal needs to be given arguments to run.\n"
" Refer to \"wal -h\" for more info.")
exit(1)
# -q
if args.q:
sys.stdout = sys.stderr = open(os.devnull, "w")
s.Args.notify = False
# -c
if args.c:
shutil.rmtree(s.CACHE_DIR / "schemes")
util.create_cache_dir()
# -r
if args.r:
gen_colors.reload_colors(args.t)
# -v
if args.v:
print(f"wal {__version__}")
exit(0)
# -i
if args.i:
image = gen_colors.get_image(args.i)
s.ColorType.plain = gen_colors.get_colors(image)
if not args.n:
wallpaper.set_wallpaper(image)
# Set the colors.
set_colors.send_sequences(s.ColorType.plain, args.t)
export.export_colors(s.ColorType.plain)
# -o
if args.o:
util.disown(args.o)
def main():
"""Main script function."""
util.create_cache_dir()
args = get_args()
process_args(args)
# This saves 10ms.
# pylint: disable=W0212
# os._exit(0)
if __name__ == "__main__":
main() main()

71
pywal/export.py Normal file
View File

@ -0,0 +1,71 @@
"""
Export colors in various formats.
"""
import shutil
import subprocess
from pywal import settings as s
from pywal import util
def save_colors(colors, export_file, message):
"""Export colors to var format."""
colors = "\n".join(colors)
util.save_file(f"{colors}\n", s.CACHE_DIR / export_file)
print(f"export: exported {message}.")
def export_rofi(colors):
"""Append rofi colors to the x_colors list."""
s.ColorType.xrdb.append(f"rofi.color-window: {colors[0]}, "
f"{colors[0]}, {colors[10]}")
s.ColorType.xrdb.append(f"rofi.color-normal: {colors[0]}, "
f"{colors[15]}, {colors[0]}, "
f"{colors[10]}, {colors[0]}")
s.ColorType.xrdb.append(f"rofi.color-active: {colors[0]}, "
f"{colors[15]}, {colors[0]}, "
f"{colors[10]}, {colors[0]}")
s.ColorType.xrdb.append(f"rofi.color-urgent: {colors[0]}, "
f"{colors[9]}, {colors[0]}, "
f"{colors[9]}, {colors[15]}")
def export_emacs(colors):
"""Set emacs colors."""
s.ColorType.xrdb.append(f"emacs*background: {colors[0]}")
s.ColorType.xrdb.append(f"emacs*foreground: {colors[15]}")
def reload_xrdb(export_file):
"""Merge the colors into the X db so new terminals use them."""
if shutil.which("xrdb"):
subprocess.call(["xrdb", "-merge", s.CACHE_DIR / export_file])
def reload_i3():
"""Reload i3 colors."""
if shutil.which("i3-msg"):
util.disown("i3-msg", "reload")
def export_colors(colors):
"""Export colors in various formats."""
save_colors(s.ColorType.plain, "colors", "plain hex colors")
save_colors(s.ColorType.shell, "colors.sh", "shell variables")
# Web based colors.
s.ColorType.css.append("}")
save_colors(s.ColorType.css, "colors.css", "css variables")
save_colors(s.ColorType.scss, "colors.scss", "scss variables")
# Text editor based colors.
save_colors(s.ColorType.putty, "colors-putty.reg", "putty theme")
# X based colors.
export_rofi(colors)
export_emacs(colors)
save_colors(s.ColorType.xrdb, "xcolors", "xrdb colors")
# i3 colors.
reload_xrdb("xcolors")
reload_i3()

157
pywal/gen_colors.py Normal file
View File

@ -0,0 +1,157 @@
"""
Generate a colorscheme.
"""
import os
import pathlib
import random
import re
import shutil
import subprocess
from pywal import settings as s
from pywal import set_colors
from pywal import util
CACHE_DIR = s.CACHE_DIR
COLOR_COUNT = s.COLOR_COUNT
def get_image(img):
"""Validate image input."""
# Check if the user has Imagemagick installed.
if not shutil.which("convert"):
print("error: imagemagick not found, exiting...\n"
"error: wal requires imagemagick to function.")
exit(1)
image = pathlib.Path(img)
if image.is_file():
wal_img = image
# Pick a random image from the directory.
elif image.is_dir():
file_types = (".png", ".jpg", ".jpeg", ".jpe", ".gif")
# Get the filename of the current wallpaper.
current_img = pathlib.Path(CACHE_DIR / "wal")
if current_img.is_file():
current_img = util.read_file(current_img)
current_img = os.path.basename(current_img[0])
# Get a list of images.
images = [img for img in os.listdir(image)
if img.endswith(file_types) and
img != current_img]
wal_img = random.choice(images)
wal_img = pathlib.Path(image / wal_img)
else:
print("error: No valid image file found.")
exit(1)
print("image: Using image", wal_img)
return str(wal_img)
def imagemagick(color_count, img):
"""Call Imagemagick to generate a scheme."""
colors = subprocess.Popen(["convert", img, "+dither", "-colors",
str(color_count), "-unique-colors", "txt:-"],
stdout=subprocess.PIPE)
return colors.stdout.readlines()
def gen_colors(img):
"""Generate a color palette using imagemagick."""
# Generate initial scheme.
raw_colors = imagemagick(COLOR_COUNT, img)
# If imagemagick finds less than 16 colors, use a larger source number
# of colors.
index = 0
while len(raw_colors) - 1 < COLOR_COUNT:
index += 1
raw_colors = imagemagick(COLOR_COUNT + index, img)
print("colors: Imagemagick couldn't generate a", COLOR_COUNT,
"color palette, trying a larger palette size",
COLOR_COUNT + index)
# Remove the first element, which isn't a color.
del raw_colors[0]
# Create a list of hex colors.
return [re.search("#.{6}", str(col)).group(0) for col in raw_colors]
def get_colors(img):
"""Generate a colorscheme using imagemagick."""
# Cache the wallpaper name.
util.save_file(img, CACHE_DIR / "wal")
# Cache the sequences file.
cache_file = pathlib.Path(CACHE_DIR / "schemes" / img.replace("/", "_"))
if cache_file.is_file():
colors = util.read_file(cache_file)
print("colors: Found cached colorscheme.")
else:
print("colors: Generating a colorscheme...")
util.notify("wal: Generating a colorscheme...")
# Generate the colors.
colors = gen_colors(img)
colors = sort_colors(colors)
# Cache the colorscheme.
util.save_file("\n".join(colors), cache_file)
print("colors: Generated colorscheme")
util.notify("wal: Generation complete.")
return colors
def sort_colors(colors):
"""Sort the generated colors."""
sorted_colors = []
sorted_colors.append(colors[0])
sorted_colors.append(colors[9])
sorted_colors.append(colors[10])
sorted_colors.append(colors[11])
sorted_colors.append(colors[12])
sorted_colors.append(colors[13])
sorted_colors.append(colors[14])
sorted_colors.append(colors[15])
sorted_colors.append(set_colors.set_grey(colors))
sorted_colors.append(colors[9])
sorted_colors.append(colors[10])
sorted_colors.append(colors[11])
sorted_colors.append(colors[12])
sorted_colors.append(colors[13])
sorted_colors.append(colors[14])
sorted_colors.append(colors[15])
return sorted_colors
def reload_colors(vte):
"""Reload colors."""
sequence_file = pathlib.Path(CACHE_DIR / "sequences")
if sequence_file.is_file():
sequences = "".join(util.read_file(sequence_file))
# If vte mode was used, remove the problem sequence.
if vte:
sequences = re.sub(r"\]708;\#.{6}", "", sequences)
# Make the terminal interpret escape sequences.
print(util.fix_escape(sequences), end="")
exit(0)

92
pywal/set_colors.py Normal file
View File

@ -0,0 +1,92 @@
"""
Send sequences to all open terminals.
"""
import os
from pywal import settings as s
from pywal import util
def set_special(index, color):
"""Build the escape sequence for special colors."""
s.ColorType.sequences.append(f"\\033]{index};{color}\\007")
if index == 10:
s.ColorType.xrdb.append(f"URxvt*foreground: {color}")
s.ColorType.xrdb.append(f"XTerm*foreground: {color}")
elif index == 11:
s.ColorType.xrdb.append(f"URxvt*background: {color}")
s.ColorType.xrdb.append(f"XTerm*background: {color}")
elif index == 12:
s.ColorType.xrdb.append(f"URxvt*cursorColor: {color}")
s.ColorType.xrdb.append(f"XTerm*cursorColor: {color}")
elif index == 66:
s.ColorType.xrdb.append(f"*.color{index}: {color}")
s.ColorType.xrdb.append(f"*color{index}: {color}")
s.ColorType.sequences.append(f"\\033]4;{index};{color}\\007")
def set_color(index, color):
"""Build the escape sequence we need for each color."""
s.ColorType.xrdb.append(f"*.color{index}: {color}")
s.ColorType.xrdb.append(f"*color{index}: {color}")
s.ColorType.sequences.append(f"\\033]4;{index};{color}\\007")
s.ColorType.shell.append(f"color{index}='{color}'")
s.ColorType.css.append(f"\t--color{index}: {color};")
s.ColorType.scss.append(f"$color{index}: {color};")
rgb = util.hex_to_rgb(color)
s.ColorType.putty.append(f"\"Colour{index}\"=\"{rgb}\"")
def set_grey(colors):
"""Set a grey color based on brightness of color0."""
return {
0: "#666666",
1: "#666666",
2: "#757575",
3: "#999999",
4: "#999999",
5: "#8a8a8a",
6: "#a1a1a1",
7: "#a1a1a1",
8: "#a1a1a1",
9: "#a1a1a1",
}.get(int(colors[0][1]), colors[7])
def send_sequences(colors, vte):
"""Send colors to all open terminals."""
set_special(10, colors[15])
set_special(11, colors[0])
set_special(12, colors[15])
set_special(13, colors[15])
set_special(14, colors[0])
# This escape sequence doesn"t work in VTE terminals.
if not vte:
set_special(708, colors[0])
# Create the sequences.
# pylint: disable=W0106
[set_color(num, color) for num, color in enumerate(colors)]
# Set a blank color that isn"t affected by bold highlighting.
set_special(66, colors[0])
# Make the terminal interpret escape sequences.
sequences = util.fix_escape("".join(s.ColorType.sequences))
# Get a list of terminals.
terminals = [f"/dev/pts/{term}" for term in os.listdir("/dev/pts/")
if len(term) < 4]
terminals.append(s.CACHE_DIR / "sequences")
# Send the sequences to all open terminals.
# pylint: disable=W0106
[util.save_file(sequences, term) for term in terminals]
print("colors: Set terminal colors")

33
pywal/settings.py Normal file
View File

@ -0,0 +1,33 @@
"""
Global variables and classes.
"""
import pathlib
__version__ = "0.1.6"
# Internal variables.
COLOR_COUNT = 16
CACHE_DIR = pathlib.Path.home() / ".cache/wal/"
# pylint: disable=too-few-public-methods
class ColorType(object):
"""Store colors in various formats."""
plain = []
xrdb = []
sequences = []
shell = []
scss = []
css = [":root {"]
putty = [
"Windows Registry Editor Version 5.00",
"[HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions\\Wal]",
]
# pylint: disable=too-few-public-methods
class Args(object):
"""Store args."""
notify = True

54
pywal/util.py Normal file
View File

@ -0,0 +1,54 @@
"""
Misc helper functions.
"""
import os
import pathlib
import subprocess
import shutil
from pywal import settings as s
def read_file(input_file):
"""Read colors from a file."""
return open(input_file).read().splitlines()
def save_file(colors, export_file):
"""Write the colors to the file."""
with open(export_file, "w") as file:
file.write(colors)
def create_cache_dir():
"""Alias to create the cache dir."""
pathlib.Path(s.CACHE_DIR / "schemes").mkdir(parents=True, exist_ok=True)
def hex_to_rgb(color):
"""Convert a hex color to rgb."""
red, green, blue = list(bytes.fromhex(color.strip("#")))
return f"{red},{green},{blue}"
def fix_escape(string):
"""Decode a string."""
return bytes(string, "utf-8").decode("unicode_escape")
def notify(msg):
"""Send arguements to notify-send."""
if shutil.which("notify-send") and s.Args.notify:
subprocess.Popen(["notify-send", msg],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
preexec_fn=os.setpgrp)
def disown(*cmd):
"""Call a system command in the background,
disown it and hide it's output."""
subprocess.Popen(["nohup"] + list(cmd),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
preexec_fn=os.setpgrp)

View File

@ -1,584 +0,0 @@
"""
wal - Generate and change colorschemes on the fly.
Created by Dylan Araps.
"""
import argparse
import os
import pathlib
import random
import re
import shutil
import subprocess
import sys
__version__ = "0.1.6"
# Internal variables.
COLOR_COUNT = 16
CACHE_DIR = pathlib.Path.home() / ".cache/wal/"
# pylint: disable=too-few-public-methods
class ColorType(object):
"""Store colors in various formats."""
plain = []
xrdb = []
sequences = []
shell = []
scss = []
css = [":root {"]
putty = [
"Windows Registry Editor Version 5.00",
"[HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions\\Wal]",
]
# pylint: disable=too-few-public-methods
class Args(object):
"""Store args."""
notify = True
# ARGS {{{
def get_args():
"""Get the script arguments."""
description = "wal - Generate colorschemes on the fly"
arg = argparse.ArgumentParser(description=description)
# Add the args.
arg.add_argument("-c", action="store_true",
help="Delete all cached colorschemes.")
arg.add_argument("-i", metavar="\"/path/to/img.jpg\"",
help="Which image or directory to use.")
arg.add_argument("-n", action="store_true",
help="Skip setting the wallpaper.")
arg.add_argument("-o", metavar="\"script_name\"",
help="External script to run after \"wal\".")
arg.add_argument("-q", action="store_true",
help="Quiet mode, don\"t print anything and \
don't display notifications.")
arg.add_argument("-r", action="store_true",
help="Reload current colorscheme.")
arg.add_argument("-t", action="store_true",
help="Fix artifacts in VTE Terminals. \
(Termite, xfce4-terminal)")
arg.add_argument("-v", action="store_true",
help="Print \"wal\" version.")
return arg.parse_args()
def process_args(args):
"""Process args."""
# If no args were passed.
if not len(sys.argv) > 1:
print("error: wal needs to be given arguments to run.\n"
" Refer to \"wal -h\" for more info.")
exit(1)
# -q
if args.q:
sys.stdout = sys.stderr = open(os.devnull, "w")
Args.notify = False
# -c
if args.c:
shutil.rmtree(CACHE_DIR / "schemes")
create_cache_dir()
# -r
if args.r:
reload_colors(args.t)
# -v
if args.v:
print(f"wal {__version__}")
exit(0)
# -i
if args.i:
image = get_image(args.i)
ColorType.plain = get_colors(image)
if not args.n:
set_wallpaper(image)
# Set the colors.
send_sequences(ColorType.plain, args.t)
export_colors(ColorType.plain)
# -o
if args.o:
disown(args.o)
# }}}
# COLORSCHEME GENERATION {{{
def get_image(img):
"""Validate image input."""
# Check if the user has Imagemagick installed.
if not shutil.which("convert"):
print("error: imagemagick not found, exiting...\n"
"error: wal requires imagemagick to function.")
exit(1)
image = pathlib.Path(img)
if image.is_file():
wal_img = image
# Pick a random image from the directory.
elif image.is_dir():
file_types = (".png", ".jpg", ".jpeg", ".jpe", ".gif")
# Get the filename of the current wallpaper.
current_img = pathlib.Path(CACHE_DIR / "wal")
if current_img.is_file():
current_img = read_file(current_img)
current_img = os.path.basename(current_img[0])
# Get a list of images.
images = [img for img in os.listdir(image)
if img.endswith(file_types) and
img != current_img]
wal_img = random.choice(images)
wal_img = pathlib.Path(image / wal_img)
else:
print("error: No valid image file found.")
exit(1)
print("image: Using image", wal_img)
return str(wal_img)
def imagemagick(color_count, img):
"""Call Imagemagick to generate a scheme."""
colors = subprocess.Popen(["convert", img, "+dither", "-colors",
str(color_count), "-unique-colors", "txt:-"],
stdout=subprocess.PIPE)
return colors.stdout.readlines()
def gen_colors(img):
"""Generate a color palette using imagemagick."""
# Generate initial scheme.
raw_colors = imagemagick(COLOR_COUNT, img)
# If imagemagick finds less than 16 colors, use a larger source number
# of colors.
index = 0
while len(raw_colors) - 1 < COLOR_COUNT:
index += 1
raw_colors = imagemagick(COLOR_COUNT + index, img)
print("colors: Imagemagick couldn't generate a", COLOR_COUNT,
"color palette, trying a larger palette size",
COLOR_COUNT + index)
# Remove the first element, which isn't a color.
del raw_colors[0]
# Create a list of hex colors.
return [re.search("#.{6}", str(col)).group(0) for col in raw_colors]
def get_colors(img):
"""Generate a colorscheme using imagemagick."""
# Cache the wallpaper name.
save_file(img, CACHE_DIR / "wal")
# Cache the sequences file.
cache_file = pathlib.Path(CACHE_DIR / "schemes" / img.replace("/", "_"))
if cache_file.is_file():
colors = read_file(cache_file)
print("colors: Found cached colorscheme.")
else:
print("colors: Generating a colorscheme...")
notify("wal: Generating a colorscheme...")
# Generate the colors.
colors = gen_colors(img)
colors = sort_colors(colors)
# Cache the colorscheme.
save_file("\n".join(colors), cache_file)
print("colors: Generated colorscheme")
notify("wal: Generation complete.")
return colors
def sort_colors(colors):
"""Sort the generated colors."""
sorted_colors = []
sorted_colors.append(colors[0])
sorted_colors.append(colors[9])
sorted_colors.append(colors[10])
sorted_colors.append(colors[11])
sorted_colors.append(colors[12])
sorted_colors.append(colors[13])
sorted_colors.append(colors[14])
sorted_colors.append(colors[15])
sorted_colors.append(set_grey(colors))
sorted_colors.append(colors[9])
sorted_colors.append(colors[10])
sorted_colors.append(colors[11])
sorted_colors.append(colors[12])
sorted_colors.append(colors[13])
sorted_colors.append(colors[14])
sorted_colors.append(colors[15])
return sorted_colors
# }}}
# SEND SEQUENCES {{{
def set_special(index, color):
"""Build the escape sequence for special colors."""
ColorType.sequences.append(f"\\033]{index};{color}\\007")
if index == 10:
ColorType.xrdb.append(f"URxvt*foreground: {color}")
ColorType.xrdb.append(f"XTerm*foreground: {color}")
elif index == 11:
ColorType.xrdb.append(f"URxvt*background: {color}")
ColorType.xrdb.append(f"XTerm*background: {color}")
elif index == 12:
ColorType.xrdb.append(f"URxvt*cursorColor: {color}")
ColorType.xrdb.append(f"XTerm*cursorColor: {color}")
elif index == 66:
ColorType.xrdb.append(f"*.color{index}: {color}")
ColorType.xrdb.append(f"*color{index}: {color}")
ColorType.sequences.append(f"\\033]4;{index};{color}\\007")
def set_color(index, color):
"""Build the escape sequence we need for each color."""
ColorType.xrdb.append(f"*.color{index}: {color}")
ColorType.xrdb.append(f"*color{index}: {color}")
ColorType.sequences.append(f"\\033]4;{index};{color}\\007")
ColorType.shell.append(f"color{index}='{color}'")
ColorType.css.append(f"\t--color{index}: {color};")
ColorType.scss.append(f"$color{index}: {color};")
rgb = hex_to_rgb(color)
ColorType.putty.append(f"\"Colour{index}\"=\"{rgb}\"")
def set_grey(colors):
"""Set a grey color based on brightness of color0."""
return {
0: "#666666",
1: "#666666",
2: "#757575",
3: "#999999",
4: "#999999",
5: "#8a8a8a",
6: "#a1a1a1",
7: "#a1a1a1",
8: "#a1a1a1",
9: "#a1a1a1",
}.get(int(colors[0][1]), colors[7])
def send_sequences(colors, vte):
"""Send colors to all open terminals."""
set_special(10, colors[15])
set_special(11, colors[0])
set_special(12, colors[15])
set_special(13, colors[15])
set_special(14, colors[0])
# This escape sequence doesn"t work in VTE terminals.
if not vte:
set_special(708, colors[0])
# Create the sequences.
# pylint: disable=W0106
[set_color(num, color) for num, color in enumerate(colors)]
# Set a blank color that isn"t affected by bold highlighting.
set_special(66, colors[0])
# Make the terminal interpret escape sequences.
sequences = fix_escape("".join(ColorType.sequences))
# Get a list of terminals.
terminals = [f"/dev/pts/{term}" for term in os.listdir("/dev/pts/")
if len(term) < 4]
terminals.append(CACHE_DIR / "sequences")
# Send the sequences to all open terminals.
# pylint: disable=W0106
[save_file(sequences, term) for term in terminals]
print("colors: Set terminal colors")
# }}}
# WALLPAPER SETTING {{{
def get_desktop_env():
"""Identify the current running desktop environment."""
desktop = os.getenv("XDG_CURRENT_DESKTOP")
if desktop:
return desktop
desktop = os.getenv("DESKTOP_SESSION")
if desktop:
return desktop
desktop = os.getenv("GNOME_DESKTOP_SESSION_ID")
if desktop:
return "GNOME"
desktop = os.getenv("MATE_DESKTOP_SESSION_ID")
if desktop:
return "MATE"
def xfconf(path, img):
"""Call xfconf to set the wallpaper on XFCE."""
disown("xfconf-query", "--channel", "xfce4-desktop",
"--property", path, "--set", img)
def set_desktop_wallpaper(desktop, img):
"""Set the wallpaper for the desktop environment."""
desktop = str(desktop).lower()
if "xfce" in desktop or "xubuntu" in desktop:
# XFCE requires two commands since they differ between versions.
xfconf("/backdrop/screen0/monitor0/image-path", img)
xfconf("/backdrop/screen0/monitor0/workspace0/last-image", img)
elif "muffin" in desktop or "cinnamon" in desktop:
subprocess.Popen(["gsettings", "set",
"org.cinnamon.desktop.background",
"picture-uri", "file:///" + img])
elif "gnome" in desktop:
subprocess.Popen(["gsettings", "set",
"org.gnome.desktop.background",
"picture-uri", "file:///" + img])
elif "mate" in desktop:
subprocess.Popen(["gsettings", "set", "org.mate.background",
"picture-filename", img])
def set_wallpaper(img):
"""Set the wallpaper."""
desktop = get_desktop_env()
if desktop:
set_desktop_wallpaper(desktop, img)
else:
if shutil.which("feh"):
subprocess.Popen(["feh", "--bg-fill", img])
elif shutil.which("nitrogen"):
subprocess.Popen(["nitrogen", "--set-zoom-fill", img])
elif shutil.which("bgs"):
subprocess.Popen(["bgs", img])
elif shutil.which("hsetroot"):
subprocess.Popen(["hsetroot", "-fill", img])
elif shutil.which("habak"):
subprocess.Popen(["habak", "-mS", img])
else:
print("error: No wallpaper setter found.")
return
print("wallpaper: Set the new wallpaper")
return 0
# }}}
# EXPORT COLORS {{{
def save_colors(colors, export_file, message):
"""Export colors to var format."""
colors = "\n".join(colors)
save_file(f"{colors}\n", CACHE_DIR / export_file)
print(f"export: exported {message}.")
def export_rofi(colors):
"""Append rofi colors to the x_colors list."""
ColorType.xrdb.append(f"rofi.color-window: {colors[0]}, "
f"{colors[0]}, {colors[10]}")
ColorType.xrdb.append(f"rofi.color-normal: {colors[0]}, "
f"{colors[15]}, {colors[0]}, "
f"{colors[10]}, {colors[0]}")
ColorType.xrdb.append(f"rofi.color-active: {colors[0]}, "
f"{colors[15]}, {colors[0]}, "
f"{colors[10]}, {colors[0]}")
ColorType.xrdb.append(f"rofi.color-urgent: {colors[0]}, "
f"{colors[9]}, {colors[0]}, "
f"{colors[9]}, {colors[15]}")
def export_emacs(colors):
"""Set emacs colors."""
ColorType.xrdb.append(f"emacs*background: {colors[0]}")
ColorType.xrdb.append(f"emacs*foreground: {colors[15]}")
def reload_xrdb(export_file):
"""Merge the colors into the X db so new terminals use them."""
if shutil.which("xrdb"):
subprocess.call(["xrdb", "-merge", CACHE_DIR / export_file])
def reload_i3():
"""Reload i3 colors."""
if shutil.which("i3-msg"):
disown("i3-msg", "reload")
def export_colors(colors):
"""Export colors in various formats."""
save_colors(ColorType.plain, "colors", "plain hex colors")
save_colors(ColorType.shell, "colors.sh", "shell variables")
# Web based colors.
ColorType.css.append("}")
save_colors(ColorType.css, "colors.css", "css variables")
save_colors(ColorType.scss, "colors.scss", "scss variables")
# Text editor based colors.
save_colors(ColorType.putty, "colors-putty.reg", "putty theme")
# X based colors.
export_rofi(colors)
export_emacs(colors)
save_colors(ColorType.xrdb, "xcolors", "xrdb colors")
# i3 colors.
reload_xrdb("xcolors")
reload_i3()
# }}}
# OTHER FUNCTIONS {{{
def reload_colors(vte):
"""Reload colors."""
sequence_file = pathlib.Path(CACHE_DIR / "sequences")
if sequence_file.is_file():
sequences = "".join(read_file(sequence_file))
# If vte mode was used, remove the problem sequence.
if vte:
sequences = re.sub(r"\]708;\#.{6}", "", sequences)
# Make the terminal interpret escape sequences.
print(fix_escape(sequences), end="")
exit(0)
def read_file(input_file):
"""Read colors from a file."""
return open(input_file).read().splitlines()
def save_file(colors, export_file):
"""Write the colors to the file."""
with open(export_file, "w") as file:
file.write(colors)
def create_cache_dir():
"""Alias to create the cache dir."""
pathlib.Path(CACHE_DIR / "schemes").mkdir(parents=True, exist_ok=True)
def hex_to_rgb(color):
"""Convert a hex color to rgb."""
red, green, blue = list(bytes.fromhex(color.strip("#")))
return f"{red},{green},{blue}"
def fix_escape(string):
"""Decode a string."""
return bytes(string, "utf-8").decode("unicode_escape")
def notify(msg):
"""Send arguements to notify-send."""
if shutil.which("notify-send") and Args.notify:
subprocess.Popen(["notify-send", msg],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
preexec_fn=os.setpgrp)
def disown(*cmd):
"""Call a system command in the background,
disown it and hide it's output."""
subprocess.Popen(["nohup"] + list(cmd),
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
preexec_fn=os.setpgrp)
# }}}
def main():
"""Main script function."""
create_cache_dir()
args = get_args()
process_args(args)
# This saves 10ms.
# pylint: disable=W0212
# os._exit(0)
if __name__ == "__main__":
main()

84
pywal/wallpaper.py Normal file
View File

@ -0,0 +1,84 @@
"""Set the wallpaper."""
import os
import shutil
import subprocess
def get_desktop_env():
"""Identify the current running desktop environment."""
desktop = os.getenv("XDG_CURRENT_DESKTOP")
if desktop:
return desktop
desktop = os.getenv("DESKTOP_SESSION")
if desktop:
return desktop
desktop = os.getenv("GNOME_DESKTOP_SESSION_ID")
if desktop:
return "GNOME"
desktop = os.getenv("MATE_DESKTOP_SESSION_ID")
if desktop:
return "MATE"
def xfconf(path, img):
"""Call xfconf to set the wallpaper on XFCE."""
disown("xfconf-query", "--channel", "xfce4-desktop",
"--property", path, "--set", img)
def set_desktop_wallpaper(desktop, img):
"""Set the wallpaper for the desktop environment."""
desktop = str(desktop).lower()
if "xfce" in desktop or "xubuntu" in desktop:
# XFCE requires two commands since they differ between versions.
xfconf("/backdrop/screen0/monitor0/image-path", img)
xfconf("/backdrop/screen0/monitor0/workspace0/last-image", img)
elif "muffin" in desktop or "cinnamon" in desktop:
subprocess.Popen(["gsettings", "set",
"org.cinnamon.desktop.background",
"picture-uri", "file:///" + img])
elif "gnome" in desktop:
subprocess.Popen(["gsettings", "set",
"org.gnome.desktop.background",
"picture-uri", "file:///" + img])
elif "mate" in desktop:
subprocess.Popen(["gsettings", "set", "org.mate.background",
"picture-filename", img])
def set_wallpaper(img):
"""Set the wallpaper."""
desktop = get_desktop_env()
if desktop:
set_desktop_wallpaper(desktop, img)
else:
if shutil.which("feh"):
subprocess.Popen(["feh", "--bg-fill", img])
elif shutil.which("nitrogen"):
subprocess.Popen(["nitrogen", "--set-zoom-fill", img])
elif shutil.which("bgs"):
subprocess.Popen(["bgs", img])
elif shutil.which("hsetroot"):
subprocess.Popen(["hsetroot", "-fill", img])
elif shutil.which("habak"):
subprocess.Popen(["habak", "-mS", img])
else:
print("error: No wallpaper setter found.")
return
print("wallpaper: Set the new wallpaper")
return 0

View File

@ -1,6 +1,6 @@
"""wal - setup.py""" """wal - setup.py"""
from setuptools import setup from setuptools import setup
import pywal import pywal.__main__ as pywal
DESC = ( DESC = (
@ -11,7 +11,7 @@ DESC = (
DESC = "".join(DESC) DESC = "".join(DESC)
VERSION = pywal.wal.__version__ VERSION = pywal.__version__
DOWNLOAD_URL = f"https://github.com/dylanaraps/pywal/archive/{VERSION}.tar.gz" DOWNLOAD_URL = f"https://github.com/dylanaraps/pywal/archive/{VERSION}.tar.gz"