From 56752098787f990324923e703f4a35848ee2b5b9 Mon Sep 17 00:00:00 2001 From: Daylin Morgan Date: Tue, 14 Jun 2022 18:35:47 -0500 Subject: [PATCH] second commit --- .flake8 | 15 ++ .gitignore | 160 ++++++++++++++++ .pre-commit-config.yaml | 23 +++ Makefile | 37 ++++ README.md | 85 +++++++++ assets/logo.svg | 143 ++++++++++++++ assets/logo.txt | 7 + assets/themes/cat_frappe.svg | 135 +++++++++++++ assets/themes/cat_latte.svg | 135 +++++++++++++ assets/themes/cat_macchiato.svg | 135 +++++++++++++ assets/themes/cat_mocha.svg | 135 +++++++++++++ assets/themes/dimmed_monokai.svg | 135 +++++++++++++ assets/themes/monokai.svg | 135 +++++++++++++ assets/themes/night_owlish.svg | 135 +++++++++++++ assets/themes/rich-default.svg | 135 +++++++++++++ assets/themes/rich_default.svg | 135 +++++++++++++ assets/yartsu.svg | 135 +++++++++++++ docs/themes.md | 26 +++ pdm.lock | 316 +++++++++++++++++++++++++++++++ preamble.py | 22 +++ pyproject.toml | 44 +++++ scripts/catppuccin-colors | 72 +++++++ scripts/theme-showcase-gen | 20 ++ yartsu/__init__.py | 1 + yartsu/_run_cmd.py | 61 ++++++ yartsu/_version.py | 6 + yartsu/argparse.py | 146 ++++++++++++++ yartsu/cli.py | 122 ++++++++++++ yartsu/term.py | 53 ++++++ yartsu/themes.py | 144 ++++++++++++++ 30 files changed, 2853 insertions(+) create mode 100644 .flake8 create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 Makefile create mode 100644 assets/logo.svg create mode 100644 assets/logo.txt create mode 100644 assets/themes/cat_frappe.svg create mode 100644 assets/themes/cat_latte.svg create mode 100644 assets/themes/cat_macchiato.svg create mode 100644 assets/themes/cat_mocha.svg create mode 100644 assets/themes/dimmed_monokai.svg create mode 100644 assets/themes/monokai.svg create mode 100644 assets/themes/night_owlish.svg create mode 100644 assets/themes/rich-default.svg create mode 100644 assets/themes/rich_default.svg create mode 100644 assets/yartsu.svg create mode 100644 docs/themes.md create mode 100644 pdm.lock create mode 100644 preamble.py create mode 100644 pyproject.toml create mode 100755 scripts/catppuccin-colors create mode 100755 scripts/theme-showcase-gen create mode 100644 yartsu/__init__.py create mode 100644 yartsu/_run_cmd.py create mode 100644 yartsu/_version.py create mode 100644 yartsu/argparse.py create mode 100644 yartsu/cli.py create mode 100644 yartsu/term.py create mode 100644 yartsu/themes.py diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..585ef84 --- /dev/null +++ b/.flake8 @@ -0,0 +1,15 @@ +[flake8] +ignore = E203, E266, E501, W503, F403 +exclude = + .git, + __pycache__, + .venv + old, + build, + dist, + preamble.py + +max-line-length = 88 +max-complexity = 18 +select = B,C,E,F,W,T4,B9 +per-file-ignores = __init__.py:F401 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4f87715 --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +capture.svg +.pdm.toml +# Created by https://www.toptal.com/developers/gitignore/api/python +# Edit at https://www.toptal.com/developers/gitignore?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# End of https://www.toptal.com/developers/gitignore/api/python diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..da16308 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,23 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 + hooks: + - id: trailing-whitespace + exclude: ".svg$" + - id: end-of-file-fixer + - id: check-added-large-files + - repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + language_version: python + - repo: https://github.com/pycqa/flake8 + rev: 4.0.1 + hooks: + - id: flake8 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e141b2a --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +SRC_FILES = $(wildcard yartsu/*) + +.PHONY: list lint build svg-docs theme-docs docs typing format +lint: format typing + +typing: + pdm run mypy yartsu + +format: + pdm run pre-commit run --all + +build: build/yartsu + +build/yartsu: $(SRC_FILES) + mkdir -p build + shiv \ + -c yartsu \ + -o ./build/yartsu \ + --preamble preamble.py \ + --reproducible \ + . + +install-bin: build/yartsu + cp ./build/yartsu ~/bin + +docs: svg-docs theme-docs + +theme-docs: + ./scripts/theme-showcase-gen + +svg-docs: + lolcat -F .5 -S 9 -f assets/logo.txt | yartsu -o assets/logo.svg + yartsu -o assets/yartsu.svg -t "yartsu --help" -- yartsu -h + +# https://stackoverflow.com/a/26339924 +list: + @LC_ALL=C $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' diff --git a/README.md b/README.md index 984a02f..992f5c3 100644 --- a/README.md +++ b/README.md @@ -1 +1,86 @@ # YARTSU + +yartsu, another rich terminal screenshot utility + +![YARTSU LOGO](https://github.com/daylinmorgan/yartsu/blob/main/assets/logo.svg) +![YARTSU HELP](https://github.com/daylinmorgan/yartsu/blob/main/assets/yartsu.svg) + +**NOTE**: this is a currently in a beta release and the API is subject to change (feedback welcome) + +Inspired by recent commits in the wonderful library [`rich`](https://github.com/Textualize/rich) I decided to write ` yartsu`. + +I needed to programatically generate screenshots for documentation purposes. The new `export_svg` methods in `rich` were a godsend. +So I wanted to try to make this feature a little more generalizable to program ouptut outside of `rich`/`python`. +Hopefully, you find it useful. + +If you come across anything unexpected please submit an issue. + +## Install + +```bash +pip install yartsu +``` + + + +## Usage + +Getting a properly formatted output from a terminal screenshot is challenging. + +There are three options for generating a screenshot. + +If one of the below option causes you any headaches consider first trying a different option. + +### Option 1: Pipes + +Many tools that color output (i.e. `grep` or `ls`) additionally allow +you to force ANSI color codes to be included even when piping output. + +In these cases you can simply pipe the output directly into `yartsu` + +```bash +ls --color=always / | yartsu -w 50 -o assets/ls_color.svg +``` + +### Option 2: Subprocess/Pty + +With this option `yartsu` will deploy a `subprocess` and `pty` +to run your command for you in an attempt to preserve ANSI. + +Note with this option you need to seperate +the command you want to run with `yartsu` args using `--`. + +```bash +yartsu -w 50 -o assets/ls_color.svg -- ls --color / +``` + +### Option 3: Text File + +Finally, if you neither of the above options work and you can +manage to preserve the codes in a plain text file you can pass this as input to `yartsu`. + +```bash +ls --color / > ls.txt +yartsu -w 50 -i ls.txt -o assets/ls_color.svg +``` + +By default svgs will be saved at `./capture.svg`. + +Additionally, for options 1 and 3 you may want to define your own title with `-t/--title`. +For option 2 the title will by default be the cmd ran by `yartsu`. + +### Themes: + +There are a number of themes you can use to style output. +Use `yartsu --list-themes` to see the available options. +Then you can specify the theme you want with `--theme`, i.e. `yartsu --theme rich_default`. +You may also use the environment variable `YARTSU_THEME`. + +See [here](https://github.com/daylinmorgan/yartsu/blob/main/docs/themes.md) a preview of the available themes + +## TODO + +- [ ] add unit tests +- [ ] add support for nerd-fonts +- [ ] add optional shadow +- [ ] add more themes diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 0000000..1be7c6b --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu + + + + + + + + + + ____ +_[]_/____\__n_ +|_____.--.__()_|_ +|LI//#\\|_______||______ +|\\__//||||/_`|'_|_(_-<||| +|'--'|\_,\__,_|_|\__/__/\_,_| +'--------------'|__/ + + + + diff --git a/assets/logo.txt b/assets/logo.txt new file mode 100644 index 0000000..f9214bf --- /dev/null +++ b/assets/logo.txt @@ -0,0 +1,7 @@ + ____ + _[]_/____\__n_ +|_____.--.__()_| _ +|LI //# \\ | _ _ __ _ _ _| |_ ____ _ +| \\__// | | || / _` | '_| _(_-< || | +| '--' | \_, \__,_|_| \__/__/\_,_| +'--------------' |__/ diff --git a/assets/themes/cat_frappe.svg b/assets/themes/cat_frappe.svg new file mode 100644 index 0000000..48d08c1 --- /dev/null +++ b/assets/themes/cat_frappe.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme cat_frappe + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/cat_latte.svg b/assets/themes/cat_latte.svg new file mode 100644 index 0000000..b4d1ab2 --- /dev/null +++ b/assets/themes/cat_latte.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme cat_latte + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/cat_macchiato.svg b/assets/themes/cat_macchiato.svg new file mode 100644 index 0000000..c117083 --- /dev/null +++ b/assets/themes/cat_macchiato.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme cat_macchiato + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/cat_mocha.svg b/assets/themes/cat_mocha.svg new file mode 100644 index 0000000..5cffeaa --- /dev/null +++ b/assets/themes/cat_mocha.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme cat_mocha + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/dimmed_monokai.svg b/assets/themes/dimmed_monokai.svg new file mode 100644 index 0000000..4534f14 --- /dev/null +++ b/assets/themes/dimmed_monokai.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme dimmed_monokai + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/monokai.svg b/assets/themes/monokai.svg new file mode 100644 index 0000000..953ae62 --- /dev/null +++ b/assets/themes/monokai.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme monokai + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/night_owlish.svg b/assets/themes/night_owlish.svg new file mode 100644 index 0000000..1b501d8 --- /dev/null +++ b/assets/themes/night_owlish.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme night_owlish + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/rich-default.svg b/assets/themes/rich-default.svg new file mode 100644 index 0000000..1fd8e93 --- /dev/null +++ b/assets/themes/rich-default.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme rich-default + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/themes/rich_default.svg b/assets/themes/rich_default.svg new file mode 100644 index 0000000..8988891 --- /dev/null +++ b/assets/themes/rich_default.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --theme rich_default + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/assets/yartsu.svg b/assets/yartsu.svg new file mode 100644 index 0000000..f1d21ab --- /dev/null +++ b/assets/yartsu.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yartsu --help + + + + + + + + + + usage: + +    ls --color=always | yartsu [options] +OR +    yartsu [options] -- ls --color +OR +    ls --color=always > ls.txt; yartsu -i ls.txt + +convert terminal output to svg + +options: +-h--help           show this help message and exit +-V--version        show program's version number and exit +-i--input INPUT    input file [default: stdin] +-o--output OUTPUT  output svg file [default: capture.svg] +-t--title TITLE    title for terminal window +-w--width WIDTH    width of svg +--theme THEME        theme to use for highlighting [default: cat_mocha] +--list-themes        list available themes + + + + diff --git a/docs/themes.md b/docs/themes.md new file mode 100644 index 0000000..fb8a5d6 --- /dev/null +++ b/docs/themes.md @@ -0,0 +1,26 @@ +# Themes + + +## cat_mocha +![cat_mocha](../assets/themes/cat_mocha.svg) + +## cat_frappe +![cat_frappe](../assets/themes/cat_frappe.svg) + +## cat_macchiato +![cat_macchiato](../assets/themes/cat_macchiato.svg) + +## cat_latte +![cat_latte](../assets/themes/cat_latte.svg) + +## monokai +![monokai](../assets/themes/monokai.svg) + +## dimmed_monokai +![dimmed_monokai](../assets/themes/dimmed_monokai.svg) + +## night_owlish +![night_owlish](../assets/themes/night_owlish.svg) + +## rich_default +![rich_default](../assets/themes/rich_default.svg) diff --git a/pdm.lock b/pdm.lock new file mode 100644 index 0000000..d80ebfe --- /dev/null +++ b/pdm.lock @@ -0,0 +1,316 @@ +[[package]] +name = "cfgv" +version = "3.3.1" +requires_python = ">=3.6.1" +summary = "Validate configuration and produce human readable error messages." + +[[package]] +name = "commonmark" +version = "0.9.1" +summary = "Python parser for the CommonMark Markdown spec" + +[[package]] +name = "distlib" +version = "0.3.4" +summary = "Distribution utilities" + +[[package]] +name = "filelock" +version = "3.6.0" +requires_python = ">=3.7" +summary = "A platform independent file lock." + +[[package]] +name = "identify" +version = "2.5.0" +requires_python = ">=3.7" +summary = "File identification library for Python" + +[[package]] +name = "importlib-metadata" +version = "4.11.4" +requires_python = ">=3.7" +summary = "Read metadata from Python packages" +dependencies = [ + "typing-extensions>=3.6.4; python_version < \"3.8\"", + "zipp>=0.5", +] + +[[package]] +name = "mypy" +version = "0.961" +requires_python = ">=3.6" +summary = "Optional static typing for Python" +dependencies = [ + "mypy-extensions>=0.4.3", + "tomli>=1.1.0; python_version < \"3.11\"", + "typed-ast<2,>=1.4.0; python_version < \"3.8\"", + "typing-extensions>=3.10", +] + +[[package]] +name = "mypy-extensions" +version = "0.4.3" +summary = "Experimental type system extensions for programs checked with the mypy typechecker." + +[[package]] +name = "nodeenv" +version = "1.6.0" +summary = "Node.js virtual environment builder" + +[[package]] +name = "platformdirs" +version = "2.5.2" +requires_python = ">=3.7" +summary = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." + +[[package]] +name = "pre-commit" +version = "2.19.0" +requires_python = ">=3.7" +summary = "A framework for managing and maintaining multi-language pre-commit hooks." +dependencies = [ + "cfgv>=2.0.0", + "identify>=1.0.0", + "importlib-metadata; python_version < \"3.8\"", + "nodeenv>=0.11.1", + "pyyaml>=5.1", + "toml", + "virtualenv>=20.0.8", +] + +[[package]] +name = "pygments" +version = "2.12.0" +requires_python = ">=3.6" +summary = "Pygments is a syntax highlighting package written in Python." + +[[package]] +name = "pyyaml" +version = "6.0" +requires_python = ">=3.6" +summary = "YAML parser and emitter for Python" + +[[package]] +name = "rich" +version = "12.4.4" +requires_python = ">=3.6.3,<4.0.0" +summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +dependencies = [ + "commonmark<0.10.0,>=0.9.0", + "pygments<3.0.0,>=2.6.0", + "typing-extensions<5.0,>=4.0.0; python_version < \"3.9\"", +] + +[[package]] +name = "six" +version = "1.16.0" +requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python 2 and 3 compatibility utilities" + +[[package]] +name = "toml" +version = "0.10.2" +requires_python = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +summary = "Python Library for Tom's Obvious, Minimal Language" + +[[package]] +name = "tomli" +version = "2.0.1" +requires_python = ">=3.7" +summary = "A lil' TOML parser" + +[[package]] +name = "typed-ast" +version = "1.5.4" +requires_python = ">=3.6" +summary = "a fork of Python 2 and 3 ast modules with type comment support" + +[[package]] +name = "typing-extensions" +version = "4.2.0" +requires_python = ">=3.7" +summary = "Backported and Experimental Type Hints for Python 3.7+" + +[[package]] +name = "virtualenv" +version = "20.14.1" +requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +summary = "Virtual Python Environment builder" +dependencies = [ + "distlib<1,>=0.3.1", + "filelock<4,>=3.2", + "importlib-metadata>=0.12; python_version < \"3.8\"", + "platformdirs<3,>=2", + "six<2,>=1.9.0", +] + +[[package]] +name = "zipp" +version = "3.8.0" +requires_python = ">=3.7" +summary = "Backport of pathlib-compatible object wrapper for zip files" + +[metadata] +lock_version = "3.1" +content_hash = "sha256:cd0296df924304b4efef3a618f6d40e9dbd72f780d80bfb7ca3907b44f4990bd" + +[metadata.files] +"cfgv 3.3.1" = [ + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, +] +"commonmark 0.9.1" = [ + {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"}, + {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"}, +] +"distlib 0.3.4" = [ + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, +] +"filelock 3.6.0" = [ + {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, + {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, +] +"identify 2.5.0" = [ + {file = "identify-2.5.0-py2.py3-none-any.whl", hash = "sha256:3acfe15a96e4272b4ec5662ee3e231ceba976ef63fd9980ed2ce9cc415df393f"}, + {file = "identify-2.5.0.tar.gz", hash = "sha256:c83af514ea50bf2be2c4a3f2fb349442b59dc87284558ae9ff54191bff3541d2"}, +] +"importlib-metadata 4.11.4" = [ + {file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"}, + {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"}, +] +"mypy 0.961" = [ + {file = "mypy-0.961-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e"}, + {file = "mypy-0.961-py3-none-any.whl", hash = "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66"}, + {file = "mypy-0.961-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0"}, + {file = "mypy-0.961-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15"}, + {file = "mypy-0.961-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3"}, + {file = "mypy-0.961-cp310-cp310-win_amd64.whl", hash = "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24"}, + {file = "mypy-0.961-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723"}, + {file = "mypy-0.961-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b"}, + {file = "mypy-0.961-cp36-cp36m-win_amd64.whl", hash = "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d"}, + {file = "mypy-0.961-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813"}, + {file = "mypy-0.961-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e"}, + {file = "mypy-0.961-cp37-cp37m-win_amd64.whl", hash = "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a"}, + {file = "mypy-0.961-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6"}, + {file = "mypy-0.961-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6"}, + {file = "mypy-0.961-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d"}, + {file = "mypy-0.961-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b"}, + {file = "mypy-0.961-cp38-cp38-win_amd64.whl", hash = "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569"}, + {file = "mypy-0.961-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932"}, + {file = "mypy-0.961-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5"}, + {file = "mypy-0.961-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648"}, + {file = "mypy-0.961-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950"}, + {file = "mypy-0.961-cp39-cp39-win_amd64.whl", hash = "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56"}, + {file = "mypy-0.961.tar.gz", hash = "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492"}, +] +"mypy-extensions 0.4.3" = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] +"nodeenv 1.6.0" = [ + {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, + {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, +] +"platformdirs 2.5.2" = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] +"pre-commit 2.19.0" = [ + {file = "pre_commit-2.19.0-py2.py3-none-any.whl", hash = "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10"}, + {file = "pre_commit-2.19.0.tar.gz", hash = "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615"}, +] +"pygments 2.12.0" = [ + {file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"}, + {file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"}, +] +"pyyaml 6.0" = [ + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +"rich 12.4.4" = [ + {file = "rich-12.4.4-py3-none-any.whl", hash = "sha256:d2bbd99c320a2532ac71ff6a3164867884357da3e3301f0240090c5d2fdac7ec"}, + {file = "rich-12.4.4.tar.gz", hash = "sha256:4c586de507202505346f3e32d1363eb9ed6932f0c2f63184dea88983ff4971e2"}, +] +"six 1.16.0" = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +"toml 0.10.2" = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] +"tomli 2.0.1" = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] +"typed-ast 1.5.4" = [ + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, + {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, + {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, + {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, + {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, + {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, + {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, + {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, + {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, + {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, + {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, + {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, + {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, + {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, + {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, + {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, + {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, + {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, +] +"typing-extensions 4.2.0" = [ + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, +] +"virtualenv 20.14.1" = [ + {file = "virtualenv-20.14.1-py2.py3-none-any.whl", hash = "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a"}, + {file = "virtualenv-20.14.1.tar.gz", hash = "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"}, +] +"zipp 3.8.0" = [ + {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, + {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, +] diff --git a/preamble.py b/preamble.py new file mode 100644 index 0000000..22c69f5 --- /dev/null +++ b/preamble.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import shutil +from pathlib import Path + +# These variables are injected by shiv.bootstrap +site_packages: Path +env: "shiv.bootstrap.environment.Environment" + +# Get a handle of the current PYZ's site_packages directory +current = site_packages.parent + +# The parent directory of the site_packages directory is our shiv cache +cache_path = current.parent + + +name, build_id = current.name.split("_") + +if __name__ == "__main__": + for path in cache_path.iterdir(): + if path.name.startswith(f"{name}_") and not path.name.endswith(build_id): + shutil.rmtree(path) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..800e61c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,44 @@ +[project] +name = "yartsu" +description = "yartsu, another rich terminal screenshot utility" +authors = [ + {name = "Daylin Morgan", email = "daylinmorgan@gmail.com"}, +] +dependencies = [ + "rich>=12.3.0", + "importlib-metadata>=4.11.4; python_version < \"3.8\"", +] +requires-python = ">=3.7" +license = {text = "MIT"} +dynamic = ["version"] + +[project.scripts] +yartsu = "yartsu.cli:main" + +[project.optional-dependencies] +[tool.pdm] +version = {use_scm = true} + +[tool.pdm.dev-dependencies] +dev = [ + "pre-commit>=2.18.1", + "mypy>=0.961", +] +[build-system] +requires = ["pdm-pep517>=0.12.0"] +build-backend = "pdm.pep517.api" + +[tool.isort] +profile = "black" +multi_line_output = 3 + +[tool.mypy] +check_untyped_defs = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +disallow_untyped_decorators = true +disallow_any_unimported = true +warn_return_any = true +warn_unused_ignores = true +no_implicit_optional = true +show_error_codes = true diff --git a/scripts/catppuccin-colors b/scripts/catppuccin-colors new file mode 100755 index 0000000..a50c374 --- /dev/null +++ b/scripts/catppuccin-colors @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +if [[ -z $1 ]]; then + echo "Usage: catppuccin-colors " + echo "i.e. mocha,frappe,macchiato,latte" + exit 1 +fi + +if ! [[ -x "$(command -v inkcat)" ]]; then + echo "inkcat is not installed" + echo "you can use npm,pnpm, or yarn to install" + exit 1 +fi + +get-color() { + local palette=$1 + local color=$2 + inkcat $palette $color --no-copy --format rgb | sed s'/rgb//g' +} + +declare -A colors bright_colors +colors=( + [black]=$(get-color $1 subtext1) + [red]=$(get-color $1 red) + [green]=$(get-color $1 green) + [yellow]=$(get-color $1 yellow) + [blue]=$(get-color $1 blue) + [magenta]=$(get-color $1 pink) + [cyan]=$(get-color $1 teal) + [white]=$(get-color $1 surface2) +) +bright_colors=( + [black]=$(get-color $1 subtext0) + [red]=$(get-color $1 red) + [green]=$(get-color $1 green) + [yellow]=$(get-color $1 yellow) + [blue]=$(get-color $1 blue) + [magenta]=$(get-color $1 pink) + [cyan]=$(get-color $1 teal) + [white]=$(get-color $1 surface1) +) + +make-palette() { + + echo "cat_${1} = Theme(" + echo " background = $(get-color $1 base)," + echo " foreground = $(get-color $1 text)," + echo " colors = Colors(" + for color in "${!colors[@]}"; do + echo " $color = ${colors[$color]}," + done + echo " )," + + echo " bright_colors = Colors(" + for color in "${!bright_colors[@]}"; do + echo " $color = ${bright_colors[$color]}," + done + echo " )," + echo ")" + + echo "CAT_${1^^} = TerminalTheme( + cat_${1}.background, + cat_${1}.foreground, + cat_${1}.colors, + cat_${1}.bright_colors, + )" + +} + +for palette in "$@"; do + make-palette $palette +done diff --git a/scripts/theme-showcase-gen b/scripts/theme-showcase-gen new file mode 100755 index 0000000..d01976c --- /dev/null +++ b/scripts/theme-showcase-gen @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +THEME_MD="./docs/themes.md" + +themes=$(yartsu --list-themes | tail -n +2 | awk '{print $2}') + +mkdir -p ./assets/themes +rm -f $THEME_MD + +echo "# Themes" >>$THEME_MD +echo >>$THEME_MD +for theme in $themes; do + url="assets/themes/${theme}.svg" + echo >>$THEME_MD + echo "## $theme" >>$THEME_MD + echo "![$theme](../$url)" >>$THEME_MD + yartsu --theme $theme -o $url -t "yartsu --theme ${theme}" -- yartsu -h +done + +echo "finished." diff --git a/yartsu/__init__.py b/yartsu/__init__.py new file mode 100644 index 0000000..8dee4bf --- /dev/null +++ b/yartsu/__init__.py @@ -0,0 +1 @@ +from ._version import __version__ diff --git a/yartsu/_run_cmd.py b/yartsu/_run_cmd.py new file mode 100644 index 0000000..bb6b93d --- /dev/null +++ b/yartsu/_run_cmd.py @@ -0,0 +1,61 @@ +import errno +import fcntl +import os +import pty +import shlex +import shutil +import struct +import sys +import termios +from itertools import chain +from select import select +from subprocess import Popen +from typing import Tuple + +( + _COLUMNS, + _ROWS, +) = shutil.get_terminal_size(fallback=(80, 20)) + + +def _set_size(fd) -> None: # type: ignore + """Found at: https://stackoverflow.com/a/6420070""" + size = struct.pack("HHHH", _ROWS, _COLUMNS, 0, 0) + fcntl.ioctl(fd, termios.TIOCSWINSZ, size) + + +def run_cmd(cmd: str) -> Tuple[int, str]: + captured_output = [] + parents, children = zip(pty.openpty(), pty.openpty()) + for fd in chain(parents, children): + _set_size(fd) + + with Popen( + shlex.split(cmd), stdin=sys.stdin, stdout=children[0], stderr=children[1] + ) as p: + for fd in children: + os.close(fd) # no input + readable = { + parents[0]: sys.stdout.buffer, # store buffers seperately + parents[1]: sys.stderr.buffer, + } + while readable: + for fd in select(readable, [], [])[0]: + try: + data = os.read(fd, 1024) # read available + except OSError as e: + if e.errno != errno.EIO: + raise # XXX cleanup + del readable[fd] # EIO means EOF on some systems + else: + if not data: # EOF + del readable[fd] + else: + if fd == parents[0]: # We caught stdout + captured_output.append(data.decode("utf-8")) + else: + captured_output.append(data.decode("utf-8")) + readable[fd].flush() + for fd in parents: + os.close(fd) + return p.returncode, "".join(captured_output) diff --git a/yartsu/_version.py b/yartsu/_version.py new file mode 100644 index 0000000..90d8220 --- /dev/null +++ b/yartsu/_version.py @@ -0,0 +1,6 @@ +try: + from importlib.metadata import version +except ImportError: + from importlib_metadata import version + +__version__ = version("yartsu") diff --git a/yartsu/argparse.py b/yartsu/argparse.py new file mode 100644 index 0000000..374b218 --- /dev/null +++ b/yartsu/argparse.py @@ -0,0 +1,146 @@ +import sys +from argparse import ONE_OR_MORE, SUPPRESS, ZERO_OR_MORE, Action +from argparse import ArgumentParser as StdArgParser +from argparse import HelpFormatter as StdHelpFormatter +from typing import Any, NoReturn, Tuple, Union + +from rich.text import Text + +from .term import term + + +class CustomFormatter(StdHelpFormatter): + def _format_action_invocation(self, action: Action) -> str: + if not action.option_strings: + (metavar,) = self._metavar_formatter(action, action.dest)(1) + return metavar + else: + # parts will be iterable of Text objects + parts = [] + # if the Optional doesn't take a value, format is: + # -s, --long + if action.nargs == 0: + parts.extend( + [Text(option, style="option") for option in action.option_strings] + ) + + # if the Optional takes a value, format is: + # -s ARGS, --long ARGS + # change to + # -s, --long ARGS + else: + default = action.dest.upper() + args_string = self._format_args(action, default) + parts.extend( + [Text(option, style="option") for option in action.option_strings] + ) + # add metavar to last string + parts[-1].append_text(Text(f" {args_string}", style="metavar")) + return term.stylize(Text(", ").join(parts)) + + # from argparse.RawDescriptionHelpFormatter + def _fill_text(self, text: str, width: int, indent: str) -> str: + return term.stylize( + Text("").join( + Text.from_markup(indent + line) + for line in text.splitlines(keepends=True) + ) + ) + + def start_section(self, heading: str) -> None: # type: ignore + return super().start_section(term.stylize(heading, style="header")) + + def _format_action(self, action: Action) -> str: + # determine the required width and the entry label + help_position = min(self._action_max_length + 2, self._max_help_position) + help_width = max(self._width - help_position, 11) + action_width = help_position - self._current_indent - 2 + action_header = self._format_action_invocation(action) + action_header_len = Text.from_ansi(action_header).cell_len + + tup: Union[Tuple[int, str, int, str], Tuple[int, str, str]] + + # no help; start on same line and add a final newline + if not action.help: + tup = self._current_indent, "", action_header + action_header = "%*s%s\n" % tup + + # short action name; start on the same line and pad two spaces + elif action_header_len <= action_width: + tup = self._current_indent, "", action_width, action_header + action_header = f"{' '*self._current_indent}{action_header}{' '*(action_width+2 - action_header_len)}" + indent_first = 0 + + # long action name; start on the next line + else: + tup = self._current_indent, "", action_header + action_header = "%*s%s\n" % tup + indent_first = help_position + + # collect the pieces of the action help + parts = [action_header] + + # if there was help for the action, add lines of help text + if action.help and action.help.strip(): + help_text = self._expand_help(action) + if help_text: + help_lines = self._split_lines(help_text, help_width) + parts.append("%*s%s\n" % (indent_first, "", help_lines[0])) + for line in help_lines[1:]: + parts.append("%*s%s\n" % (help_position, "", line)) + + # or add a newline if the description doesn't end with one + elif not action_header.endswith("\n"): + parts.append("\n") + + # if there are any sub-actions, add their help as well + for subaction in self._iter_indented_subactions(action): + parts.append(self._format_action(subaction)) + + # return a single string + return self._join_parts(parts) + + def _get_invocation_length(self, invocation: Any) -> int: + return Text.from_ansi(invocation).cell_len + + def _format_args(self, action: Action, default_metavar: str) -> str: + get_metavar = self._metavar_formatter(action, default_metavar) + if action.nargs == ZERO_OR_MORE: + return "[%s ...]" % get_metavar(1) + elif action.nargs == ONE_OR_MORE: + return "%s ..." % get_metavar(1) + else: + return super()._format_args(action, default_metavar) + + def add_argument(self, action: Action) -> None: + if action.help is not SUPPRESS: + + # find all invocations + get_invocation = self._format_action_invocation + invocations = [get_invocation(action)] + for subaction in self._iter_indented_subactions(action): + invocations.append(get_invocation(subaction)) + + # update the maximum item length accounting for ansi codes from rich + invocation_length = max(map(self._get_invocation_length, invocations)) + action_length = invocation_length + self._current_indent + self._action_max_length = max(self._action_max_length, action_length) + + # add the item to the list + self._add_item(self._format_action, [action]) + + +class ArgumentParser(StdArgParser): + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.formatter_class = CustomFormatter + + def error(self, message: str) -> NoReturn: + """error(message: string) + Prints a usage message incorporating the message to stderr and + exits. + If you override this in a subclass, it should not return -- it + should either exit or raise an exception. + """ + term.print(f"[YartsuCLIError]({self.prog.strip()}): {message}", err=True) + sys.exit(1) diff --git a/yartsu/cli.py b/yartsu/cli.py new file mode 100644 index 0000000..18eefaf --- /dev/null +++ b/yartsu/cli.py @@ -0,0 +1,122 @@ +import os +import sys +import textwrap +from argparse import SUPPRESS, FileType, Namespace +from pathlib import Path + +from rich.console import Console +from rich.text import Text + +from ._run_cmd import run_cmd +from ._version import __version__ +from .argparse import ArgumentParser +from .term import term +from .themes import THEMES + +DEFAULT_THEME = os.getenv("YARTSU_THEME", "cat_mocha") + + +def get_args() -> Namespace: + + parser = ArgumentParser( + usage=SUPPRESS, + description=textwrap.dedent( + r""" + [bold italic cyan]usage[/]: + + ls --color=always | yartsu \[options] + [dim]OR[/] + yartsu \[options] -- ls --color + [dim]OR[/] + ls --color=always > ls.txt; yartsu -i ls.txt + + convert terminal output to svg + """ + ), + ) + parser.add_argument( + "-V", "--version", action="version", version=f"%(prog)s {__version__}" + ) + parser.add_argument( + "-i", + "--input", + help="input file [default: stdin]", + type=FileType("r"), + default=(None if sys.stdin.isatty() else sys.stdin), + ) + parser.add_argument("cmd", type=str, nargs="*", default="", help=SUPPRESS) + parser.add_argument( + "-o", + "--output", + help="output svg file [default: %(default)s]", + type=Path, + default=Path("capture.svg"), + ) + parser.add_argument("-t", "--title", help="title for terminal window", type=str) + parser.add_argument("-w", "--width", help="width of svg", type=int) + parser.add_argument( + "--theme", + help="theme to use for highlighting [default: %(default)s]", + type=str, + default=DEFAULT_THEME, + ) + parser.add_argument( + "--list-themes", help="list available themes", action="store_true" + ) + return parser.parse_args() + + +def main() -> None: + args = get_args() + console = Console(record=True) + + if args.list_themes: + term.print("Available themes:") + term.print("\n".join([" - " + theme for theme in THEMES])) + sys.exit(0) + + if args.cmd and args.input or not (args.cmd or args.input): + term.print( + "[UsageError]: either use the --input option " + "OR pipe terminal output to yartsu", + err=True, + ) + term.print("See 'yartsu --help' for more information", err=True) + sys.exit(1) + + if args.theme not in THEMES: + term.print(f"[ThemeError]: {args.theme} is not a valid theme", err=True) + sys.exit(1) + + if args.cmd: + cmd = " ".join(args.cmd) + + try: + returncode, captured_output = run_cmd(cmd) + except FileNotFoundError: + term.print(f"[CmdError]: issue running {cmd}", err=True) + sys.exit(1) + + if returncode != 0: + term.print(f"[CmdError]: issue running {cmd}", err=True) + sys.exit(returncode) + + parsed_input = Text.from_ansi(captured_output) + else: + cmd = None + + if args.input: + parsed_input = Text.from_ansi(args.input.read()) + + title = args.title or cmd or "yartsu" + + if not args.width: + console.width = max(console.measure(parsed_input).maximum, 40) + else: + console.width = args.width + + console.print(parsed_input) + + console.save_svg(args.output, title=title, theme=THEMES[args.theme]) + + term.print(f"\nSaved to {args.output}.") diff --git a/yartsu/term.py b/yartsu/term.py new file mode 100644 index 0000000..211ae30 --- /dev/null +++ b/yartsu/term.py @@ -0,0 +1,53 @@ +import shutil +from typing import Any + +from rich import box +from rich.console import Console +from rich.highlighter import RegexHighlighter +from rich.table import Table as RichTable +from rich.theme import Theme + +MAX_WIDTH = 120 + + +class Table(RichTable): + def __init__(self, box: box.Box = box.ROUNDED, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.box = box + + +class ErrorHighlighter(RegexHighlighter): + """Apply style to anything that looks like an error.""" + + highlights = [r"(?P\[\w+Error\])"] + + +theme = Theme({"header": "bold cyan", "option": "yellow", "metavar": "green"}) + + +class Term: + def __init__(self, width: int) -> None: + + self.console = Console(highlight=False, theme=theme, width=width) + self.err_console = Console( + theme=Theme({"error": "bold red"}, inherit=True), + stderr=True, + highlighter=ErrorHighlighter(), + width=width, + ) + + def print(self, *objects: Any, err: bool = False, **kwargs: Any) -> None: + console = self.console if not err else self.err_console + console.print(*objects, **kwargs) + + def stylize(self, *objects: Any, **kwargs: Any) -> str: + with self.console.capture() as capture: + self.print(*objects, **kwargs, end="") + return capture.get() + + def debug(self, renderable: Any, **kwargs: Any) -> None: + self.console.print("[dim]>>debug[/]:\n", renderable, **kwargs) + + +cols = shutil.get_terminal_size().columns +term = Term(width=MAX_WIDTH if cols > MAX_WIDTH else cols) diff --git a/yartsu/themes.py b/yartsu/themes.py new file mode 100644 index 0000000..19ededd --- /dev/null +++ b/yartsu/themes.py @@ -0,0 +1,144 @@ +from collections import namedtuple + +from rich.terminal_theme import ( + DIMMED_MONOKAI, + MONOKAI, + NIGHT_OWLISH, + SVG_EXPORT_THEME, + TerminalTheme, +) + +Colors = namedtuple("Colors", "black, red, green, yellow, blue, magenta, cyan, white") +Theme = namedtuple("Theme", "background, foreground, colors, bright_colors") + +cat_mocha = Theme( + background=(30, 30, 46), + foreground=(198, 208, 245), + colors=Colors( + black=(179, 188, 223), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(86, 89, 112), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), + bright_colors=Colors( + black=(161, 168, 201), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(67, 70, 90), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), +) +CAT_MOCHA = TerminalTheme( + cat_mocha.background, + cat_mocha.foreground, + cat_mocha.colors, + cat_mocha.bright_colors, +) +cat_frappe = Theme( + background=(48, 52, 70), + foreground=(198, 206, 239), + colors=Colors( + black=(179, 188, 223), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(86, 89, 112), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), + bright_colors=Colors( + black=(161, 168, 201), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(67, 70, 90), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), +) +CAT_FRAPPE = TerminalTheme( + cat_frappe.background, + cat_frappe.foreground, + cat_frappe.colors, + cat_frappe.bright_colors, +) +cat_macchiato = Theme( + background=(36, 39, 58), + foreground=(197, 207, 245), + colors=Colors( + black=(179, 188, 223), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(86, 89, 112), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), + bright_colors=Colors( + black=(161, 168, 201), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(67, 70, 90), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), +) +CAT_MACCHIATO = TerminalTheme( + cat_macchiato.background, + cat_macchiato.foreground, + cat_macchiato.colors, + cat_macchiato.bright_colors, +) +cat_latte = Theme( + background=(239, 241, 245), + foreground=(76, 79, 105), + colors=Colors( + black=(179, 188, 223), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(86, 89, 112), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), + bright_colors=Colors( + black=(161, 168, 201), + cyan=(148, 226, 213), + yellow=(249, 226, 175), + blue=(135, 176, 249), + red=(243, 139, 168), + white=(67, 70, 90), + green=(166, 227, 161), + magenta=(245, 194, 231), + ), +) +CAT_LATTE = TerminalTheme( + cat_latte.background, + cat_latte.foreground, + cat_latte.colors, + cat_latte.bright_colors, +) + +THEMES = { + "cat_mocha": CAT_MOCHA, + "cat_frappe": CAT_FRAPPE, + "cat_macchiato": CAT_MACCHIATO, + "cat_latte": CAT_LATTE, + "monokai": MONOKAI, + "dimmed_monokai": DIMMED_MONOKAI, + "night_owlish": NIGHT_OWLISH, + "rich_default": SVG_EXPORT_THEME, +}