Skip to content

Instantly share code, notes, and snippets.

@grassmunk
Last active October 11, 2019 06:55
Show Gist options
  • Save grassmunk/4b6887159e702761bbf6898a98e8ef62 to your computer and use it in GitHub Desktop.
Save grassmunk/4b6887159e702761bbf6898a98e8ef62 to your computer and use it in GitHub Desktop.
Microsoft Theme Parser Beta for Chicago95
#!/usr/bin/env python3
# License GPL3
# Parse Windows .theme files
# Notes: Does not work with theme names with spaces in the title
# To parse the config
import configparser
import sys
import os
# For icon conversion
import PIL.Image
import svgwrite
import os
import operator
import struct
from PIL import BmpImagePlugin, PngImagePlugin, Image
# Fix pixel2svg
import xml.etree.ElementTree as ET
import re
import subprocess
import fnmatch
# recolor
import shutil
p = os.path.join
## For ini file writting:
def get_filename(ini, name, var):
'''gets the icon'''
#ini is parsed config object
#name is the section
#var is the variable to get
if name in ini and (var in ini[name] or var.capitalize() in ini[name] or var.lower() in ini[name] or var.upper() in ini[name]):
if var in ini[name]: ico = ini[name][var]
if var.capitalize() in ini[name]: ico = ini[name][var.capitalize()]
if var.upper() in ini[name]: ico = ini[name][var.upper()]
if var.lower() in ini[name]: ico = ini[name][var.lower()]
elif "Software\\Classes\\"+name in ini and (var.capitalize() in ini["Software\\Classes\\"+name] or
var.lower() in ini["Software\\Classes\\"+name] or
var.upper() in ini["Software\\Classes\\"+name] or
var in ini["Software\\Classes\\"+name] ):
if var in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var]
if var.capitalize() in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var.capitalize()]
if var.upper() in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var.upper()]
if var.lower() in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var.lower()]
else:
return(False)
if ico == '': return(False)
if "%WinDir%" in ico: return(False)
if "%ThemeDir%" in ico:
ico = ico.replace("%ThemeDir%",'')
else:
if "\\" in ico: ico = ico.split("\\")[len(ico.split("\\"))-1]
if "," in ico: ico = ico.split(",")[0]
ico = ico.replace("\\","/")
return(ico)
def hexToRGB(h):
h = h.replace("#","")
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
def rgbaToRGB(tup):
return (tup[0],tup[1],tup[2])
def convert_with_inkscape(svg_in, size, svg_out):
#print("\t\t[Inkscape Convert]", svg_in, size, svg_out)
try:
inkscape_path = subprocess.check_output(["which", "inkscape"]).strip()
except subprocess.CalledProcessError:
print("ERROR: You need inkscape installed to use this script.")
exit(1)
size = str(size)
args = [
inkscape_path,
"--without-gui",
"-f", svg_in,
"--export-area-page",
"-w", size,
"-h", size,
"--export-png=" + svg_out
]
subprocess.check_call(args, stdout=subprocess.DEVNULL)
def fix_with_inkscape(color, tmpfile):
try:
inkscape_path = subprocess.check_output(["which", "inkscape"]).strip()
except subprocess.CalledProcessError:
print("ERROR: You need inkscape installed to use this script.")
exit(1)
#print("\t\t[Inkscape Convert]", svg_in, size, svg_out)
#cmd = "inkscape --select=" + rgbs[rgb] +" --verb EditSelectSameFillColor --verb SelectionCombine --verb SelectionUnion --verb FileSave --verb FileQuit "+ tmpfile
args = [
inkscape_path,
"--select="+color,
"--verb", "EditSelectSameFillColor",
"--verb", "SelectionCombine",
"--verb", "SelectionUnion",
"--verb", "FileSave",
"--verb", "FileQuit",
tmpfile
]
subprocess.check_call(args, stderr=subprocess.DEVNULL ,stdout=subprocess.DEVNULL)
def findfiles(filenamed, where='.'):
# filename might contain / so we pasrse it here
which = filenamed
if len(filenamed.split("/")) >= 2:
(where,which) = os.path.split(filenamed)
rule = re.compile(fnmatch.translate(which), re.IGNORECASE)
return [name for name in os.listdir(where) if rule.match(name)]
def convert_icon(folder, filename, squaresize = 20, overlap = 0, tmp_file="./chicago95_tmp_file.svg" ):
## Convert Icons to PNG
# Lots of code lifter from pixel2svg
if folder[-1] not in "/":
folder = folder + "/"
if len(filename.split("/")) >= 2:
filename = os.path.split(filename)[0]+"/"+findfiles(filename)[0]
else:
filename = findfiles(filename)[0]
image = Image.open(filename)
if len(filename.split("/")) >= 2: filename = filename.split("/")[-1]
image = image.convert("RGBA")
(width, height) = image.size
#print("[pixel2svg] Image is {0}x{1}".format(width, height))
rgb_values = list(image.getdata())
#print("[pixel2svg] Converting image to RGBA")
#print("[pixel2svg] Image is {0}x{1}".format(width, height))
rgb_values = list(image.getdata())
#print("[pixel2svg] Read {0} pixels".format(len(rgb_values)))
svgdoc = svgwrite.Drawing(filename = os.path.splitext(folder+filename)[0] + ".svg",
size = ("{0}px".format(width * squaresize),
"{0}px".format(height * squaresize)))
print("\t[convert_icon] Converting '{0}'".format(folder+filename),"to '{0}'".format(svgdoc.filename))
# If --overlap is given, use a slight overlap to prevent inaccurate SVG rendering
rectangle_size = ("{0}px".format(squaresize + overlap),
"{0}px".format(squaresize + overlap))
rowcount = 0
while rowcount < height:
#print("[pixel2svg] Processing pixel row {0} of {1}".format(rowcount + 1, height))
colcount = 0
while colcount < width:
rgb_tuple = rgb_values.pop(0)
# Omit transparent pixels
if rgb_tuple[3] > 0:
rectangle_posn = ("{0}px".format(colcount * squaresize),
"{0}px".format(rowcount * squaresize))
rectangle_fill = svgwrite.rgb(rgb_tuple[0], rgb_tuple[1], rgb_tuple[2])
alpha = rgb_tuple[3];
if alpha == 255:
svgdoc.add(svgdoc.rect(insert = rectangle_posn,
size = rectangle_size,
fill = rectangle_fill))
else:
svgdoc.add(svgdoc.rect(insert = rectangle_posn,
size = rectangle_size,
fill = rectangle_fill,
opacity = alpha/float(255)))
colcount = colcount + 1
rowcount = rowcount + 1
svgdoc.save()
# Now we need to clean up the pixel file created
#print("[fix] Creating tmp file", tmp_file)
cmd = "inkscape -l "+ tmp_file +" \"{0}\"".format(svgdoc.filename)
#print("[fix] Executing command:", cmd)
os.system(cmd)
#print("[fix] Parsing", tmp_file)
SVG_NS = "http://www.w3.org/2000/svg"
svg = ET.parse(tmp_file)
rects = svg.findall('.//{%s}rect' % SVG_NS)
rgbs = {}
#print('[fix] Getting colors and ids')
for rect in rects:
rect_id = rect.attrib['id']
rgb = rect.attrib['fill']
if rgb not in rgbs:
rgbs[rgb] = rect_id
#for rgb in rgbs:
# print('\t[id]', rgbs[rgb], rgb)
print("\t[convert_icon] Joining same colors\n\t[pixel2svg]!!! Inkscape will open and close here a {0} times".format(len(rgbs)))
count = 0
for rgb in rgbs:
if len(rgbs) >= 150:
print("\t\t[pixel2svg] File has too many colors, skipping")
break
count = count + 1
print('\t\t[',count,'/',len(rgbs),str(round((float(count)/float(len(rgbs))*100),0))+'%] Working on', rgbs[rgb], rgb)
fix_with_inkscape( rgbs[rgb] , tmp_file )
#print('[fix] Moving tmp file', tmp_file, 'to original file', svgdoc.filename)
cmd = 'mv '+tmp_file+' "'+ svgdoc.filename +'"'
os.system(cmd)
return(svgdoc.filename)
def convert_cursor(folder,icon_name,output_file):
if len(icon_name.split("/")) >= 2:
icon_name = os.path.split(icon_name)[0]+"/"+findfiles(icon_name)[0]
else:
icon_name = findfiles(icon_name)[0]
try:
convert_path = subprocess.check_output(["which", "convert"]).strip()
except subprocess.CalledProcessError:
print("ERROR: You need imagemagick installed to use this script.")
exit(1)
if folder[-1] not in "/":
folder = folder + "/"
output_file = folder+output_file + ".png"
args = [
convert_path,
icon_name,
output_file
]
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL )
def convert_ani(folder, ani_file, output_file):
if folder[-1] not in "/":
folder = folder + "/"
file_name = ani_file
if len(file_name.split("/")) >= 2:
file_name = os.path.split(file_name)[0]+"/"+findfiles(file_name)[0]
else:
file_name = findfiles(file_name)[0]
ico_counter = 1
name = file_name[:-4]
f = open(file_name,'rb')
ani_file = f.read()
f.close()
bytes = bytearray(ani_file)
file_len = len(bytes)
for i in range(0,file_len):
if i + 4 <= file_len and (bytes[i] == 0x69 and bytes[i+1] == 0x63 and bytes[i+2] == 0x6f and bytes[i+3] == 0x6e ):
new_icon_name = folder+output_file + "_{:02}".format(ico_counter) + ".ico"
ico_counter += 1
new_file = bytearray()
j = 8
while(i+j+4 <= file_len):
if bytes[i+j+1] == 0x69 and bytes[i+1] == 0x63 and bytes[i+2] == 0x6f and bytes[i+3] == 0x6e:
f = open(new_icon_name,"wb")
f.write(new_file)
f.close()
try:
convert_cursor(folder, new_icon_name, new_icon_name.split("/")[-1][:-4])
except subprocess.CalledProcessError as e:
#ignore these for now
pass
os.system("rm "+ new_icon_name)
if os.path.isfile(new_icon_name[:-4]+"-0.png"):
os.system("mv " + new_icon_name[:-4]+"-0.png " + new_icon_name[:-4]+".png")
break
if j == 10:
new_file.append(0x01)
else:
new_file.append(bytes[i+j])
j += 1
i += j
f = open(new_icon_name,"wb")
f.write(new_file)
f.close()
try:
convert_cursor(folder, new_icon_name, new_icon_name.split("/")[-1][:-4])
except subprocess.CalledProcessError as e:
#ignore these for now
pass
os.system("rm "+ new_icon_name)
if os.path.isfile(new_icon_name[:-4]+"-0.png"):
os.system("mv " + new_icon_name[:-4]+"-0.png " + new_icon_name[:-4]+".png")
return(ico_counter)
print("Microsoft Theme file parser")
if len(sys.argv) < 2:
print("Usage:",sys.argv[0]," theme_file")
sys.exit(-1)
config = configparser.RawConfigParser(interpolation=None)
config.optionxform = str
theme = sys.argv[1]
print("[Parser] Parsing Theme File:", theme)
config.read(theme)
theme_name = theme.replace(".theme",'')
theme_name = theme_name.replace(".Theme",'')
## Get the icons
print("\t[+] Grabbing Icons")
icons = {}
# Computer
icons["computer_ico"] = get_filename(config,"CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon","DefaultValue")
# Documents
icons["documents_ico"] = get_filename(config,"CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon","DefaultValue")
# Network
icons["network_ico"] = get_filename(config,"CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon","DefaultValue")
# Recycle
icons["recycle_full"] = get_filename(config,"CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon","Full")
icons["recycle_empty"] = get_filename(config,"CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon","Empty")
## Colors
print("\t[+] Grabbing Colors")
if "Control Panel\Colors" in config:
config_colors = config["Control Panel\Colors"]
colors = {}
for color in config_colors:
r = int(config_colors[color].split()[0])
g = int(config_colors[color].split()[1])
b = int(config_colors[color].split()[2])
colors[color] = '#{:02x}{:02x}{:02x}'.format(r,g,b)
## Get the cursors
print("\t[+] Grabbing Cursors")
if "Control Panel\Cursors" in config:
config_cursors = config["Control Panel\Cursors"]
cursors = {}
for cursor in config_cursors:
cursors[cursor] = get_filename(config,"Control Panel\Cursors",cursor)
## Get the wallpaper
print("\t[+] Grabbing Wallpaper")
wallpaper = get_filename(config,"Control Panel\Desktop","Wallpaper")
## Get Sound files
print("\t[+] Grabbing Sounds")
sound_names = [
"AppEvents\\Schemes\\Apps\\.Default\\AppGPFault\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\Close\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\.Default\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\MailBeep\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\Maximize\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\MenuCommand\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\MenuPopup\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\Minimize\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\Open\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\RestoreDown\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\RestoreUp\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\RingIn\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\Ringout\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\SystemDefault\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\SystemExclamation\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\SystemExit\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\SystemHand\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\SystemQuestion\\.Current",
"AppEvents\\Schemes\\Apps\\.Default\\SystemStart\\.Current",
"AppEvents\\Schemes\Apps\Explorer\EmptyRecycleBin\\.Current"
]
sounds = {}
for i in sound_names:
sound_name = i.split("\\")[-2]
if get_filename(config,i,"DefaultValue"):
wav_file = get_filename(config,i,"DefaultValue")
sounds[sound_name] = wav_file
print("\t[+] Icons:")
for i in icons: print("\t\t["+i+"]\t", icons[i])
print("\t[+] Cursors:")
for i in cursors: print("\t\t["+i+"]\t", cursors[i])
print("\t[+] Colors:")
for i in colors: print("\t\t["+i+"]\t", colors[i])
print("\t[+] Wallpaper:\n\t\t", wallpaper)
print("\t[+] Sounds:")
for i in sounds: print("\t\t["+i+"]\t", sounds[i])
## Whew we made it, now lets start processing these
# First we make a folder to put our new theme in
folder_name = theme_name + "_Chicago95"
print("[Theme] Creating new theme folders\n\tMaking folder:", folder_name)
os.mkdir(folder_name)
out_folder = folder_name+"/"+theme_name+"_"
#os.mkdir(out_folder+"Icons")
print("[DefaultIcon] Creating New Icons")
ricon_sizes = [16,22,24,32,48]
ricon_files = {"documents_ico": "folder-documents.png",
"network_ico" : "network-server.png",
"computer_ico" : "user-home.png",
"recycle_empty" : "user-trash.png",
"recycle_full": "user-trash-full.png"}
sicon_files = {"documents_ico": "folder-documents.svg",
"network_ico" : "network-server.svg",
"computer_ico" : "folder_home.svg",
"recycle_full" : "edittrash.svg",
"recycle_empty": "emptytrash.svg"}
inPath = os.path.expanduser("~/.icons/Chicago95")
outPath = out_folder+"Icons"
shutil.copytree(inPath,outPath,symlinks=True,ignore_dangling_symlinks=True)
for i in icons:
if not icons[i]: continue
converted_icon = convert_icon(outPath,icons[i])
for size in ricon_sizes:
if size <= 32 and i == "documents_ico": continue
print("\t\tplaces/"+str(size)+"/"+ricon_files[i])
sized_target = outPath+"/places/"+str(size)+"/"+ricon_files[i]
convert_with_inkscape( converted_icon, size, sized_target)
scaled_target = outPath+"/places/scalable/"+sicon_files[i]
#print(scaled_target)
shutil.copy(converted_icon, scaled_target)
# Now replace Icons
icon_theme_config = configparser.RawConfigParser(interpolation=None)
icon_theme_config.optionxform = str
icon_theme_config.read(outPath+"/index.theme")
icon_theme_config.set("Icon Theme","Name",theme_name)
with open(outPath+"/index.theme", 'w') as configfile:
icon_theme_config.write(configfile, space_around_delimiters=False)
print("[DefaultIcon] Done!")
# Parse Colors
# config
inPath = os.path.expanduser("~/.themes/Chicago95")
outPath = folder_name +"/"+theme_name+"_Theme"
remapColors = {
"#000080": colors['ActiveTitle'], #Active Window and Text Highlight - RED
"#dfdfdf": colors['Menu'], #highlight? - Does Nothing - Yellow
"#c0c0c0": colors['Menu'], #main window outline/buttons/bars color and inactive text - Green
"#ffffff": colors['Window'], #main window color inner and main text color - Blue
"#808080": colors['InactiveTitle'], #shadow window color (Inactive?) - turqoise
"#000000": colors['WindowText'], #Inactive window text color - Purple
}
print("[ControlPanel\Colors] Changing theme colors:")
for i in remapColors:
print("\t\tOriginal Color:",i,"New Color:",remapColors[i])
#Make sure none of them overlap
for x in remapColors:
if remapColors[x] in remapColors:
if remapColors[x][-1].lower() == 'f':
remapColors[x] = remapColors[x][:6] + str(254)
else:
remapColors[x] = remapColors[x][:6] + str(int(remapColors[x][-1]) + 1)
if (os.path.isdir(outPath)):
shutil.rmtree(outPath)
os.makedirs(outPath)
for root,dirs,files in os.walk(inPath):
for dir in dirs:
fpath = p(root,dir)
nfpath = fpath.replace(inPath,outPath)
if not (os.path.isdir(nfpath)):
os.makedirs(nfpath)
for file in files:
fpath = p(root,file)
nfpath = fpath.replace(inPath,outPath)
lpath = fpath.replace(inPath + "/","")
ext = os.path.splitext(fpath)[1].lower()
if (ext == ".css") or (ext == ".scss") or (ext == ".xpm") or (ext == ".svg") or (ext == ".rc")\
or (lpath == "gtk-2.0/gtkrc") or (lpath == "xfwm4/hidpi/themerc") or (lpath == "xfwm4/themerc"):
#print("[colors] editing text: " +fpath)
fileh = open(fpath,"r")
nfileh = open(nfpath,"w")
for line in fileh:
for color in remapColors:
colorV = remapColors[color]
line = line.replace(color.upper(),colorV.upper())
line = line.replace(color.lower(),colorV.lower())
nfileh.write(line)
fileh.close()
nfileh.close()
if (ext == ".png"):
#print("[colors] editing image: " +fpath)
img = Image.open(fpath)
img = img.convert("RGBA")
pixels = img.load()
width, height = img.size
for y in range(height):
for x in range(width):
pixel = pixels[x,y]
for color in remapColors:
colorV = remapColors[color]
rgbColor = hexToRGB(color)
rgbColorV = hexToRGB(colorV)
if (rgbaToRGB(pixel) == rgbColor):
pixels[x,y] = (rgbColorV[0],rgbColorV[1],rgbColorV[2],pixel[3])
break
img.save(nfpath)
img.close()
if not (os.path.isfile(nfpath)):
shutil.copy(fpath,nfpath)
# Cursors
print("[ControlPanel\Cursors] Creating Cursors")
cursor_folder = out_folder + "Cursors"
inPath = os.path.expanduser("~/.icons/Chicago95_Cursor_Black")
shutil.copytree(inPath,cursor_folder,symlinks=True,ignore_dangling_symlinks=True)
cursor_folder = cursor_folder + "/src"
pointers = {
"Arrow" : "Arrow",
"Help" : "Help",
"AppStarting" : "AppStarting",
"Wait" : "Wait",
"NWPen" : "Handwriting",
"No" : "NO",
"SizeNS" : "BaseN",
"SizeWE" : "SizeWE",
"Crosshair" : "Crosshair",
"IBeam" : "IBeam",
"SizeNWSE" : "AngleNE",
"SizeNESW" : "AngleNW",
"SizeAll" : "SizeAll",
"UpArrow" : "UpArrow"
}
for i in pointers:
if i not in cursors or not cursors[i]:
continue
print("\t\tConverting",i,"to",pointers[i])
theme_cursor = cursors[i]
x11_cursor = pointers[i]
if os.path.splitext(theme_cursor)[1] not in ".ani":
convert_cursor(cursor_folder, theme_cursor, x11_cursor)
else:
total = convert_ani(cursor_folder, theme_cursor, x11_cursor)
os.system("rm \""+cursor_folder+"/"+x11_cursor+".png\"")
with open(cursor_folder+"/"+x11_cursor+".conf") as f:
(g1, g2, g3, cursor_n) = f.readline().strip().split(" ")
write_conf = open(cursor_folder+"/"+x11_cursor+".conf", 'w')
for i in range(1,total):
cursor_string = g1+" "+g2+" "+g3+" "+x11_cursor+"_{:02}".format(i)+".png\n"
write_conf.write(cursor_string)
write_conf.close()
# All the cursors are done now, lets make a cursor folder
#subprocess.check_call("./"+cursor_folder+"/Build.sh",cwd="./"+cursor_folder,shell=True)
p = subprocess.Popen([os.getcwd()+"/"+cursor_folder+"/Build.sh"],cwd="./"+cursor_folder)
p.wait()
cur_theme_config = configparser.RawConfigParser(interpolation=None)
cur_theme_config.optionxform = str
cur_theme_config.read(out_folder + "Cursors"+"/index.theme")
cur_theme_config.set("Icon Theme","Name",theme_name)
with open(out_folder + "Cursors"+"/index.theme", 'w') as configfile:
cur_theme_config.write(configfile, space_around_delimiters=False)
os.system("rm -rf '"+out_folder + "Cursors"+"/cursors'")
os.system("mv "+cursor_folder+"/cursors "+out_folder + "Cursors"+"/cursors")
print("[ControlPanel\Cursors] Done")
print("[ControlPanel\Audio]")
os.mkdir(out_folder+"Audio")
for i in sounds:
if len(sounds[i].split("/")) >= 2:
sound = os.path.split(sounds[i])[0]+"/"+findfiles(sounds[i])[0]
else:
sound = findfiles(sounds[i])[0]
if os.path.exists(sound):
print("\t\tCopying:", i,sound)
if len(sound.split("/")) >= 2:
sound_out = sound.split("/")[-1]
else:
sound_out = sound
shutil.copy(sound,out_folder+"Audio/"+i+"_"+sound_out)
if wallpaper:
print("[Control Panel\Desktop]")
if len(wallpaper.split("/")) >= 2:
wallpaper = os.path.split(wallpaper)[0]+"/"+findfiles(wallpaper)[0]
else:
wallpaper = findfiles(wallpaper)[0]
shutil.copy(wallpaper,folder_name)
print("[Fonts]")
found = []
for root, dirs, files in os.walk(os.getcwd()):
for local_file in files:
if (local_file.endswith(".ttf") or local_file.endswith(".TTF")) and local_file not in found:
print("\tCopying:",local_file)
shutil.copy(os.path.join(root,local_file),folder_name)
found.append(local_file)
print("[DONE]\n")
print("." * 80)
print("." * 80)
print("." * 80)
print("\n\tNewly created theme is available at {0}.\n\t To install copy:\n\t\t".format(folder_name) +
"{0} to ~/.icons\n\t\t".format(out_folder+"Icons") +
"{0} to ~/.icons\n\t\t".format(out_folder+"Cursors") +
"{0} to ~/.themes\n\t\t".format(out_folder+"Theme") +
"Audio Files are located in {0}\n\t\t".format(out_folder+"Audio") +
"Fonts and Wallpapers are located in {0}\n".format(folder_name) +
"\t\t\tTo install font, put the font file in ~/.fonts and run fc-cache -f -v\n"
)
print("One liner: cp -r "+out_folder+"Cursors ~/.icons;cp -r "+out_folder+"Icons ~/.icons;cp -r "+out_folder+"Theme ~/.theme")
print("." * 80)
print("." * 80)
print("." * 80)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment