Skip to content

Instantly share code, notes, and snippets.

@YUKI2eN3e
Created November 8, 2023 06:47
Show Gist options
  • Select an option

  • Save YUKI2eN3e/fa215feee4d5d7a2c6f4586ccfc845e2 to your computer and use it in GitHub Desktop.

Select an option

Save YUKI2eN3e/fa215feee4d5d7a2c6f4586ccfc845e2 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""A single-file program for assigning icons to filenames in the `catppuccin.catppuccin-vsc-icons` vscode extension."""
import argparse
from dataclasses import dataclass
from os import listdir, path
from typing import List
class Colours:
"""ANSI color codes"""
BLACK = "\033[0;30m"
RED = "\033[0;31m"
GREEN = "\033[0;32m"
BROWN = "\033[0;33m"
BLUE = "\033[0;34m"
PURPLE = "\033[0;35m"
CYAN = "\033[0;36m"
LIGHT_GRAY = "\033[0;37m"
DARK_GRAY = "\033[1;30m"
LIGHT_RED = "\033[1;31m"
LIGHT_GREEN = "\033[1;32m"
YELLOW = "\033[1;33m"
LIGHT_BLUE = "\033[1;34m"
LIGHT_PURPLE = "\033[1;35m"
LIGHT_CYAN = "\033[1;36m"
LIGHT_WHITE = "\033[1;37m"
BOLD = "\033[1m"
FAINT = "\033[2m"
ITALIC = "\033[3m"
UNDERLINE = "\033[4m"
BLINK = "\033[5m"
NEGATIVE = "\033[7m"
CROSSED = "\033[9m"
RESET = "\033[0m"
# cancel SGR codes if we don't write to a terminal
if not __import__("sys").stdout.isatty():
for _ in dir():
if isinstance(_, str) and _[0] != "_":
locals()[_] = ""
else:
# set Windows console in VT mode
from sys import platform
if platform == "win32":
from os import system # type:ignore
system("")
VSCODE_EXTENSIONS = path.join(path.expanduser("~"), ".vscode", "extensions")
def _get_catppuccin_vsc_icons() -> str:
for extension in listdir(VSCODE_EXTENSIONS):
if "catppuccin.catppuccin-vsc-icons-" in extension:
return path.join(VSCODE_EXTENSIONS, extension)
raise FileNotFoundError
try:
CATPPUCCIN_ICONS = _get_catppuccin_vsc_icons()
except FileNotFoundError:
print(
f"{Colours.BOLD}{Colours.RED}ERROR: 'catppuccin.catppuccin-vsc-icons' not installed.{Colours.RESET}"
)
exit(1)
@dataclass
class CliArgs:
# Predefined
justfile: bool
pre_commit_config: bool
# Manual
new_filename: str | None
previous_line: str | None
existing_icon: str | None
def get_args() -> CliArgs:
parser = argparse.ArgumentParser()
parser.description = f"{Colours.BOLD}A little program for assigning icons to filenames in the {Colours.UNDERLINE}`catppuccin.catppuccin-vsc-icons`{Colours.RESET}{Colours.BOLD} vscode extension.{Colours.RESET}"
predefined = parser.add_argument_group(f"{Colours.YELLOW}Predefined{Colours.RESET}")
predefined.add_argument(
"--just",
"--justfile",
dest="justfile",
action="store_true",
default=False,
help='set "justfile"\'s to use "makefile" icon',
)
predefined.add_argument(
"--pre-commit",
"--pre-commit-config",
dest="pre_commit_config",
action="store_true",
default=False,
help='set ".pre-commit-config.yaml" files to use "git" icon',
)
manual = parser.add_argument_group(f"{Colours.YELLOW}Manual{Colours.RESET}")
manual.add_argument(
"--filename",
dest="new_filename",
default=None,
help=f'The name of the new file to set an icon for. (e.g. {Colours.DARK_GRAY}"justfile"{Colours.RESET})',
)
manual.add_argument(
"--previous-line",
dest="previous_line",
default=None,
help=f'The line after which we add out icon. (e.g. {Colours.DARK_GRAY}\'"jest.teardown.js": "jest",\'{Colours.RESET})',
)
manual.add_argument(
"--icon",
dest="existing_icon",
default=None,
help=f'The existing icon to use. (e.g. {Colours.DARK_GRAY}"makefile"{Colours.RESET})',
)
return CliArgs(**vars(parser.parse_args()))
def add_icon(
theme_path: str, new_filename: str, previous_line: str, existing_icon: str
) -> bool:
"""Add an (existing) icon for a new filename
Args:
theme_path (str): The path to the "theme.json" file. (Usually obtained by `path.join(CATPPUCCIN_ICONS, "themes", theme_name, "theme.json")`)
new_filename (str): The name of the new file to set an icon for. (e.g. `"justfile"`)
previous_line (str): The line after which we add out icon. (e.g. `'"jest.teardown.js": "jest",'`)
existing_icon (str): The existing icon to use. (e.g. `"makefile"`)
Returns:
bool: True if successful, False if not.
"""
theme_lines: List[str] = []
with open(theme_path, "r", encoding="utf8") as file:
theme_lines = file.readlines()
justfile_added = False
with open(theme_path, "w", encoding="utf8") as file:
for line in theme_lines:
file.write(line)
if previous_line in line:
file.write(
line.replace(previous_line, f'"{new_filename}": "{existing_icon}",')
)
justfile_added = True
return justfile_added
def main():
args = get_args()
manual = None not in [args.new_filename, args.previous_line, args.existing_icon]
base_dir = path.join(CATPPUCCIN_ICONS, "themes")
for theme in listdir(base_dir):
theme_file = path.join(base_dir, theme, "theme.json")
if args.justfile:
if add_icon(
theme_path=theme_file,
new_filename="justfile",
previous_line='"jest.teardown.js": "jest",',
existing_icon="makefile",
):
print(
f'{Colours.BOLD}{Colours.GREEN}Added "justfile" to: {Colours.RESET}{Colours.UNDERLINE}{theme_file}{Colours.RESET}'
)
else:
print(
f'{Colours.BOLD}{Colours.RED}Failed to add "justfile" to: {Colours.RESET}{Colours.UNDERLINE}{theme_file}{Colours.RESET}'
)
if args.pre_commit_config:
if add_icon(
theme_path=theme_file,
new_filename=".pre-commit-config.yaml",
previous_line='"pre-commit": "bash",',
existing_icon="git",
):
print(
f'{Colours.BOLD}{Colours.GREEN}Added ".pre-commit-config.yaml" to: {Colours.RESET}{Colours.UNDERLINE}{theme_file}{Colours.RESET}'
)
else:
print(
f'{Colours.BOLD}{Colours.RED}Failed to add ".pre-commit-config.yaml" to: {Colours.RESET}{Colours.UNDERLINE}{theme_file}{Colours.RESET}'
)
if manual:
if add_icon(
theme_path=theme_file,
new_filename=args.new_filename,
previous_line=args.previous_line,
existing_icon=args.existing_icon,
):
print(
f'{Colours.BOLD}{Colours.GREEN}Added "{args.new_filename}" to: {Colours.RESET}{Colours.UNDERLINE}{theme_file}{Colours.RESET}'
)
else:
print(
f'{Colours.BOLD}{Colours.RED}Failed to add "{args.new_filename}" to: {Colours.RESET}{Colours.UNDERLINE}{theme_file}{Colours.RESET}'
)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment