[
  {
    "path": ".gitattributes",
    "content": "**/*.gif filter=lfs diff=lfs merge=lfs -text\n**/*.mp4 filter=lfs diff=lfs merge=lfs -text\n**/*.webm filter=lfs diff=lfs merge=lfs -text\n**/*.png filter=lfs diff=lfs merge=lfs -text\n*.tape linguist-language=elixir\nthemes*.json linguist-generated\nTHEMES.md linguist-generated\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "* @charmbracelet/everyone\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**Setup**\nPlease complete the following information along with version numbers, if applicable.\n - OS [e.g. Ubuntu, macOS]\n - Shell [e.g. zsh, fish]\n - Terminal Emulator [e.g. kitty, iterm]\n - Terminal Multiplexer [e.g. tmux]\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Source Code**\nPlease include source code if needed to reproduce the behavior. \n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nAdd screenshots to help explain your problem.\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n- name: Discord\n  url: https://charm.sh/discord\n  about: Chat on our Discord.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\n\nupdates:\n  - package-ecosystem: \"gomod\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n      day: \"monday\"\n      time: \"05:00\"\n      timezone: \"America/New_York\"\n    labels:\n      - \"dependencies\"\n    commit-message:\n      prefix: \"chore\"\n      include: \"scope\"\n    groups:\n      all:\n        patterns:\n          - \"*\"\n    ignore:\n      - dependency-name: github.com/charmbracelet/bubbletea/v2\n        versions:\n          - v2.0.0-beta1\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n      day: \"monday\"\n      time: \"05:00\"\n      timezone: \"America/New_York\"\n    labels:\n      - \"dependencies\"\n    commit-message:\n      prefix: \"chore\"\n      include: \"scope\"\n    groups:\n      all:\n        patterns:\n          - \"*\"\n\n  - package-ecosystem: \"docker\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n      day: \"monday\"\n      time: \"05:00\"\n      timezone: \"America/New_York\"\n    labels:\n      - \"dependencies\"\n    commit-message:\n      prefix: \"chore\"\n      include: \"scope\"\n    groups:\n      all:\n        patterns:\n          - \"*\"\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: build\n\non: [push, pull_request]\n\njobs:\n  build:\n    uses: charmbracelet/meta/.github/workflows/build.yml@main\n\n  snapshot:\n    uses: charmbracelet/meta/.github/workflows/snapshot.yml@main\n    secrets:\n      goreleaser_key: ${{ secrets.GORELEASER_KEY }}\n"
  },
  {
    "path": ".github/workflows/dependabot-sync.yml",
    "content": "name: dependabot-sync\non:\n  schedule:\n    - cron: \"0 0 * * 0\" # every Sunday at midnight\n  workflow_dispatch: # allows manual triggering\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  dependabot-sync:\n    uses: charmbracelet/meta/.github/workflows/dependabot-sync.yml@main\n    with:\n      repo_name: ${{ github.event.repository.name }}\n    secrets:\n      gh_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/goreleaser.yml",
    "content": "# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json\n\nname: goreleaser\n\non:\n  push:\n    tags:\n      - v*.*.*\n\nconcurrency:\n  group: goreleaser\n  cancel-in-progress: true\n\njobs:\n  goreleaser:\n    uses: charmbracelet/meta/.github/workflows/goreleaser.yml@main\n    secrets:\n      docker_username: ${{ secrets.DOCKERHUB_USERNAME }}\n      docker_token: ${{ secrets.DOCKERHUB_TOKEN }}\n      gh_pat: ${{ secrets.PERSONAL_ACCESS_TOKEN }}\n      goreleaser_key: ${{ secrets.GORELEASER_KEY }}\n      aur_key: ${{ secrets.AUR_KEY }}\n      fury_token: ${{ secrets.FURY_TOKEN }}\n      nfpm_gpg_key: ${{ secrets.NFPM_GPG_KEY }}\n      nfpm_passphrase: ${{ secrets.NFPM_PASSPHRASE }}\n      macos_sign_p12: ${{ secrets.MACOS_SIGN_P12 }}\n      macos_sign_password: ${{ secrets.MACOS_SIGN_PASSWORD }}\n      macos_notary_issuer_id: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}\n      macos_notary_key_id: ${{ secrets.MACOS_NOTARY_KEY_ID }}\n      macos_notary_key: ${{ secrets.MACOS_NOTARY_KEY }}\n"
  },
  {
    "path": ".github/workflows/lint-sync.yml",
    "content": "name: lint-sync\non:\n  schedule:\n    # every Sunday at midnight\n    - cron: \"0 0 * * 0\"\n  workflow_dispatch: # allows manual triggering\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  lint:\n    uses: charmbracelet/meta/.github/workflows/lint-sync.yml@main\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: lint\non:\n  push:\n  pull_request:\n\njobs:\n  lint:\n    uses: charmbracelet/meta/.github/workflows/lint.yml@main\n    with:\n      golangci_path: .golangci.yml\n"
  },
  {
    "path": ".github/workflows/nightly.yml",
    "content": "name: nightly\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  nightly:\n    uses: charmbracelet/meta/.github/workflows/nightly.yml@main\n    secrets:\n      docker_username: ${{ secrets.DOCKERHUB_USERNAME }}\n      docker_token: ${{ secrets.DOCKERHUB_TOKEN }}\n      goreleaser_key: ${{ secrets.GORELEASER_KEY }}\n      macos_sign_p12: ${{ secrets.MACOS_SIGN_P12 }}\n      macos_sign_password: ${{ secrets.MACOS_SIGN_PASSWORD }}\n      macos_notary_issuer_id: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}\n      macos_notary_key_id: ${{ secrets.MACOS_NOTARY_KEY_ID }}\n      macos_notary_key: ${{ secrets.MACOS_NOTARY_KEY }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.ssh/\ncaptures/\ntmp/\nframes/\nmanpages\ncompletions\ndist\nvhs\n.idea/\n.vscode/\n"
  },
  {
    "path": ".golangci.yml",
    "content": "version: \"2\"\nrun:\n  tests: false\nlinters:\n  enable:\n    - bodyclose\n    - exhaustive\n    - goconst\n    - godot\n    - gomoddirectives\n    - goprintffuncname\n    - gosec\n    - misspell\n    - nakedret\n    - nestif\n    - nilerr\n    - noctx\n    - nolintlint\n    - prealloc\n    - revive\n    - rowserrcheck\n    - sqlclosecheck\n    - tparallel\n    - unconvert\n    - unparam\n    - whitespace\n    - wrapcheck\n  exclusions:\n    rules:\n      - text: '(slog|log)\\.\\w+'\n        linters:\n          - noctx\n      - text: \"var-naming\"\n        linters:\n          - revive\n      - text: \"G705\"\n        linters:\n          - gosec\n      - text: \"G115\"\n        linters:\n          - gosec\n      - text: \"os/exec.Command must not be called\"\n        linters:\n          - noctx\n    generated: lax\n    presets:\n      - common-false-positives\n  settings:\n    exhaustive:\n      default-signifies-exhaustive: true\nissues:\n  max-issues-per-linter: 0\n  max-same-issues: 0\nformatters:\n  enable:\n    - gofumpt\n    - goimports\n  exclusions:\n    generated: lax\n"
  },
  {
    "path": ".goreleaser.yml",
    "content": "version: 2\n\nincludes:\n  - from_url:\n      url: charmbracelet/meta/main/goreleaser-vhs.yaml\n\nvariables:\n  main: \".\"\n  description: \"A tool for recording terminal GIFs\"\n  github_url: \"https://github.com/charmbracelet/vhs\"\n  maintainer: \"Maas Lalani <maas@charm.sh>\"\n  brew_commit_author_name: \"Maas Lalani\"\n  brew_commit_author_email: \"maas@charm.sh\"\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM tsl0922/ttyd:alpine as ttyd\nFROM alpine:latest as fontcollector\n\n# Install Fonts\nRUN apk add --no-cache \\\n    --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main \\\n    --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community \\\n    --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing \\\n    font-adobe-source-code-pro font-source-code-pro-nerd \\\n    font-dejavu font-dejavu-sans-mono-nerd \\\n    font-fira-code font-fira-code-nerd \\\n    font-hack font-hack-nerd \\\n    font-ibm-plex-mono-nerd \\\n    font-inconsolata font-inconsolata-nerd \\\n    font-jetbrains-mono font-jetbrains-mono-nerd \\\n    font-liberation font-liberation-mono-nerd \\\n    font-noto \\\n    font-roboto-mono \\\n    # font-ubuntu font-ubuntu-mono-nerd \\ # Alpine no longer has this font\n    font-noto-emoji\n\nFROM debian:stable-slim\n\nRUN apt-get update\n\n# Add fonts\nCOPY --from=fontcollector /usr/share/fonts/ /usr/share/fonts\n\n# Install latest ttyd\nCOPY --from=ttyd /usr/bin/ttyd /usr/bin/ttyd\n\n# Expose port\nEXPOSE 1976\n\n# Create volume\nVOLUME /vhs\nWORKDIR /vhs\n\n# Install Dependencies\nRUN apt-get -y install ffmpeg chromium bash\n\n# Create user\nRUN useradd -u 1976 -U -s /bin/false vhs\n# Mimic alpine default color option\nRUN echo 'alias ls=\"ls --color\"' >> ~/.bashrc\n# Install\nCOPY vhs /usr/bin/\n\nENV VHS_PORT=\"1976\"\nENV VHS_HOST=\"0.0.0.0\"\nENV VHS_GID=\"1976\"\nENV VHS_UID=\"1976\"\nENV VHS_KEY_PATH=\"/vhs/vhs\"\nENV VHS_AUTHORIZED_KEYS_PATH=\"\"\nENV VHS_NO_SANDBOX=\"true\"\n\nENTRYPOINT [\"/usr/bin/vhs\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022-2023 Charmbracelet, Inc\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "themes.json:\n\t# this is the url used by https://windowsterminalthemes.dev/\n\t# See https://github.com/atomcorp/themes/blob/master/app/src/App.tsx#L18\n\t@./scripts/download_theme.sh \\\n\t\thttps://2zrysvpla9.execute-api.eu-west-2.amazonaws.com/prod/themes \\\n\t\tthemes\n\nTHEMES.md:\n\t@go run . themes --markdown 2> THEMES.md\n\nall: themes.json THEMES.md\n\t@echo \"Running all\"\n\nrefresh:\n\t@rm -rf themes.json themes.json THEMES.md\n\t@$(MAKE) all\n\n"
  },
  {
    "path": "README.md",
    "content": "# VHS\n\n<p>\n  <img src=\"https://user-images.githubusercontent.com/42545625/198402537-12ca2f6c-0779-4eb8-a67c-8db9cb3df13c.png#gh-dark-mode-only\" width=\"500\" />\n  <img src=\"https://user-images.githubusercontent.com/42545625/198402542-a305f669-a05a-4d91-b18b-ca76e72b655a.png#gh-light-mode-only\" width=\"500\" />\n  <br>\n  <a href=\"https://github.com/charmbracelet/vhs/releases\"><img src=\"https://img.shields.io/github/release/charmbracelet/vhs.svg\" alt=\"Latest Release\"></a>\n  <a href=\"https://pkg.go.dev/github.com/charmbracelet/vhs?tab=doc\"><img src=\"https://godoc.org/github.com/golang/gddo?status.svg\" alt=\"Go Docs\"></a>\n  <a href=\"https://github.com/charmbracelet/vhs/actions\"><img src=\"https://github.com/charmbracelet/vhs/workflows/build/badge.svg\" alt=\"Build Status\"></a>\n</p>\n\nWrite terminal GIFs as code for integration testing and demoing your CLI tools.\n\n<img alt=\"Welcome to VHS\" src=\"https://stuff.charm.sh/vhs/examples/neofetch_3.gif\" width=\"600\" />\n\nThe above example was generated with VHS ([view source](./examples/neofetch/neofetch.tape)).\n\n## Tutorial\n\nTo get started, [install VHS](#installation) and create a new `.tape` file.\n\n```sh\nvhs new demo.tape\n```\n\nOpen the `.tape` file with your favorite `$EDITOR`.\n\n```sh\nvim demo.tape\n```\n\nTape files consist of a series of [commands](#vhs-command-reference). The commands are\ninstructions for VHS to perform on its virtual terminal. For a list of all\npossible commands see [the command reference](#vhs-command-reference).\n\n```elixir\n# Where should we write the GIF?\nOutput demo.gif\n\n# Set up a 1200x600 terminal with 46px font.\nSet FontSize 46\nSet Width 1200\nSet Height 600\n\n# Type a command in the terminal.\nType \"echo 'Welcome to VHS!'\"\n\n# Pause for dramatic effect...\nSleep 500ms\n\n# Run the command by pressing enter.\nEnter\n\n# Admire the output for a bit.\nSleep 5s\n```\n\nOnce you've finished, save the file and feed it into VHS.\n\n```sh\nvhs demo.tape\n```\n\nAll done! You should see a new file called `demo.gif` (or whatever you named\nthe `Output`) in the directory.\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/demo.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/demo.gif\">\n  <img width=\"600\" alt=\"A GIF produced by the VHS code above\" src=\"https://stuff.charm.sh/vhs/examples/demo.gif\">\n</picture>\n\nFor more examples see the [`examples/`](https://github.com/charmbracelet/vhs/tree/main/examples) directory.\n\n## Installation\n\n> [!NOTE]\n> VHS requires [`ttyd`](https://github.com/tsl0922/ttyd) and [`ffmpeg`](https://ffmpeg.org) to be installed and available on your `PATH`.\n\nUse a package manager:\n\n```sh\n# macOS or Linux\nbrew install vhs\n\n# Arch Linux (btw)\npacman -S vhs\n\n# Nix\nnix-env -iA nixpkgs.vhs\n\n# Windows using scoop\nscoop install vhs\n```\n\nOr, use Docker to run VHS directly, dependencies included:\n\n```sh\ndocker run --rm -v $PWD:/vhs ghcr.io/charmbracelet/vhs <cassette>.tape\n```\n\nOr, download it:\n\n- [Packages][releases] are available in Debian and RPM formats\n- [Binaries][releases] are available for Linux, macOS, and Windows\n\nOr, just install it with `go`:\n\n```sh\ngo install github.com/charmbracelet/vhs@latest\n```\n\n<details>\n<summary>Windows, Debian, Ubuntu, Fedora, RHEL, Void Instructions</summary>\n\n- Debian / Ubuntu\n\n```sh\n# Debian/Ubuntu\nsudo mkdir -p /etc/apt/keyrings\ncurl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg\necho \"deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *\" | sudo tee /etc/apt/sources.list.d/charm.list\n# Install ttyd from https://github.com/tsl0922/ttyd/releases\nsudo apt update && sudo apt install vhs ffmpeg\n```\n\n- Fedora / RHEL\n\n```sh\necho '[charm]\nname=Charm\nbaseurl=https://repo.charm.sh/yum/\nenabled=1\ngpgcheck=1\ngpgkey=https://repo.charm.sh/yum/gpg.key' | sudo tee /etc/yum.repos.d/charm.repo\n# Install ttyd from https://github.com/tsl0922/ttyd/releases\nsudo yum install vhs ffmpeg\n```\n\n- Void\n\n```sh\nsudo xbps-install vhs\n```\n\n- Windows\n\n```sh\nwinget install charmbracelet.vhs\n# or scoop\nscoop install vhs\n```\n\n</details>\n\n[releases]: https://github.com/charmbracelet/vhs/releases\n\n## Record Tapes\n\nVHS has the ability to generate tape files from your terminal actions!\n\nTo record to a tape file, run:\n\n```bash\nvhs record > cassette.tape\n```\n\nPerform any actions you want and then `exit` the terminal session to stop\nrecording. You may want to manually edit the generated `.tape` file to add\nsettings or modify actions. Then, you can generate the GIF:\n\n```bash\nvhs cassette.tape\n```\n\n## Publish Tapes\n\nVHS allows you to publish your GIFs to our servers for easy sharing with your\nfriends and colleagues. Specify which file you want to share, then use the\n`publish` sub-command to host it on `vhs.charm.sh`. The output will provide you\nwith links to share your GIF via browser, HTML, and Markdown.\n\n```bash\nvhs publish demo.gif\n```\n\n## The VHS Server\n\nVHS has an SSH server built in! When you self-host VHS you can access it as\nthough it were installed locally. VHS will have access to commands and\napplications on the host, so you don't need to install them on your machine.\n\nTo start the server run:\n\n```sh\nvhs serve\n```\n\n<details>\n<summary>Configuration Options</summary>\n\n- `VHS_PORT`: The port to listen on (`1976`)\n- `VHS_HOST`: The host to listen on (`localhost`)\n- `VHS_GID`: The Group ID to run the server as (current user's GID)\n- `VHS_UID`: The User ID to run the server as (current user's UID)\n- `VHS_KEY_PATH`: The path to the SSH key to use (`.ssh/vhs_ed25519`)\n- `VHS_AUTHORIZED_KEYS_PATH`: The path to the authorized keys file (empty, publicly accessible)\n\n</details>\n\nThen, simply access VHS from a different machine via `ssh`:\n\n```sh\nssh vhs.example.com < demo.tape > demo.gif\n```\n\n## VHS Command Reference\n\n> [!NOTE]\n> You can view all VHS documentation on the command line with `vhs manual`.\n\nThere are a few basic types of VHS commands:\n\n- [`Output <path>`](#output): specify file output\n- [`Require <program>`](#require): specify required programs for tape file\n- [`Set <Setting> Value`](#settings): set recording settings\n- [`Type \"<characters>\"`](#type): emulate typing\n- [`Left`](#arrow-keys) [`Right`](#arrow-keys) [`Up`](#arrow-keys) [`Down`](#arrow-keys): arrow keys\n- [`Backspace`](#backspace) [`Enter`](#enter) [`Tab`](#tab) [`Space`](#space): special keys\n- [`ScrollUp`](#scroll-up--down) [`ScrollDown`](#scroll-up--down): scroll terminal viewport\n- [`Ctrl[+Alt][+Shift]+<char>`](#ctrl): press control + key and/or modifier\n- [`Sleep <time>`](#sleep): wait for a certain amount of time\n- [`Wait[+Screen][+Line] /regex/`](#wait): wait for specific conditions\n- [`Hide`](#hide): hide commands from output\n- [`Show`](#show): stop hiding commands from output\n- [`Screenshot`](#screenshot): screenshot the current frame\n- [`Copy/Paste`](#copy--paste): copy and paste text from clipboard.\n- [`Source`](#source): source commands from another tape\n- [`Env <Key> Value`](#env): set environment variables\n\n### Output\n\nThe `Output` command allows you to specify the location and file format\nof the render. You can specify more than one output in a tape file which\nwill render them to the respective locations.\n\n```elixir\nOutput out.gif\nOutput out.mp4\nOutput out.webm\nOutput frames/ # a directory of frames as a PNG sequence\n```\n\n### Require\n\nThe `Require` command allows you to specify dependencies for your tape file.\nThese are useful to fail early if a required program is missing from the\n`$PATH`, and it is certain that the VHS execution will not work as expected.\n\nRequire commands must be defined at the top of a tape file, before any non-\nsetting or non-output command.\n\n```elixir\n# A tape file that requires gum and glow to be in the $PATH\nRequire gum\nRequire glow\n```\n\n### Settings\n\nThe `Set` command allows you to change global aspects of the terminal, such as\nthe font settings, window dimensions, and GIF output location.\n\nSetting must be administered at the top of the tape file. Any setting (except\n`TypingSpeed`) applied after a non-setting or non-output command will be\nignored.\n\n#### Set Shell\n\nSet the shell with the `Set Shell <shell>` command\n\n```elixir\nSet Shell fish\n```\n\n#### Set Font Size\n\nSet the font size with the `Set FontSize <number>` command.\n\n```elixir\nSet FontSize 10\nSet FontSize 20\nSet FontSize 40\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-size-10.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-size-10.gif\">\n  <img width=\"600\" alt=\"Example of setting the font size to 10 pixels\" src=\"https://stuff.charm.sh/vhs/examples/font-size-10.gif\">\n</picture>\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-size-20.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-size-20.gif\">\n  <img width=\"600\" alt=\"Example of setting the font size to 20 pixels\" src=\"https://stuff.charm.sh/vhs/examples/font-size-20.gif\">\n</picture>\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-size-40.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-size-40.gif\">\n  <img width=\"600\" alt=\"Example of setting the font size to 40 pixels\" src=\"https://stuff.charm.sh/vhs/examples/font-size-40.gif\">\n</picture>\n\n#### Set Font Family\n\nSet the font family with the `Set FontFamily \"<font>\"` command\n\n```elixir\nSet FontFamily \"Monoflow\"\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-family.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/font-family.gif\">\n  <img width=\"600\" alt=\"Example of changing the font family to Monoflow\" src=\"https://stuff.charm.sh/vhs/examples/font-family.gif\">\n</picture>\n\n#### Set Width\n\nSet the width of the terminal with the `Set Width` command.\n\n```elixir\nSet Width 300\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/width.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/width.gif\">\n  <img width=\"300\" alt=\"Example of changing the width of the terminal\" src=\"https://stuff.charm.sh/vhs/examples/width.gif\">\n</picture>\n\n#### Set Height\n\nSet the height of the terminal with the `Set Height` command.\n\n```elixir\nSet Height 1000\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/height.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/height.gif\">\n  <img width=\"300\" alt=\"Example of changing the height of the terminal\" src=\"https://stuff.charm.sh/vhs/examples/height.gif\">\n</picture>\n\n#### Set Letter Spacing\n\nSet the spacing between letters (tracking) with the `Set LetterSpacing`\nCommand.\n\n```elixir\nSet LetterSpacing 20\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/letter-spacing.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/letter-spacing.gif\">\n  <img width=\"600\" alt=\"Example of changing the letter spacing to 20 pixels between characters\" src=\"https://stuff.charm.sh/vhs/examples/letter-spacing.gif\">\n</picture>\n\n#### Set Line Height\n\nSet the spacing between lines with the `Set LineHeight` Command.\n\n```elixir\nSet LineHeight 1.8\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/line-height.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/line-height.gif\">\n  <img width=\"600\" alt=\"Example of changing the line height to 1.8\" src=\"https://stuff.charm.sh/vhs/examples/line-height.gif\">\n</picture>\n\n#### Set Typing Speed\n\n```elixir\nSet TypingSpeed 500ms # 500ms\nSet TypingSpeed 1s    # 1s\n```\n\nSet the typing speed of seconds per key press. For example, a typing speed of\n`0.1` would result in a `0.1s` (`100ms`) delay between each character being typed.\n\nThis setting can also be overwritten per command with the `@<time>` syntax.\n\n```elixir\nSet TypingSpeed 0.1\nType \"100ms delay per character\"\nType@500ms \"500ms delay per character\"\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/typing-speed.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/typing-speed.gif\">\n  <img width=\"600\" alt=\"Example of using the Type command in VHS\" src=\"https://stuff.charm.sh/vhs/examples/typing-speed.gif\">\n</picture>\n\n#### Set Theme\n\nSet the theme of the terminal with the `Set Theme` command. The theme value\nshould be a JSON string with the base 16 colors and foreground + background.\n\n```elixir\nSet Theme { \"name\": \"Whimsy\", \"black\": \"#535178\", \"red\": \"#ef6487\", \"green\": \"#5eca89\", \"yellow\": \"#fdd877\", \"blue\": \"#65aef7\", \"magenta\": \"#aa7ff0\", \"cyan\": \"#43c1be\", \"white\": \"#ffffff\", \"brightBlack\": \"#535178\", \"brightRed\": \"#ef6487\", \"brightGreen\": \"#5eca89\", \"brightYellow\": \"#fdd877\", \"brightBlue\": \"#65aef7\", \"brightMagenta\": \"#aa7ff0\", \"brightCyan\": \"#43c1be\", \"brightWhite\": \"#ffffff\", \"background\": \"#29283b\", \"foreground\": \"#b3b0d6\", \"selection\": \"#3d3c58\", \"cursor\": \"#b3b0d6\" }\n```\n\n<img alt=\"Example of changing the theme to Whimsy\" src=\"https://stuff.charm.sh/vhs/examples/theme.gif\" width=\"600\" />\n\nYou can also set themes by name:\n\n```elixir\nSet Theme \"Catppuccin Frappe\"\n```\n\nSee the full list by running `vhs themes`, or in [THEMES.md](./THEMES.md).\n\n#### Set Padding\n\nSet the padding (in pixels) of the terminal frame with the `Set Padding`\ncommand.\n\n```elixir\nSet Padding 0\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/padding.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/padding.gif\">\n  <img width=\"600\" alt=\"Example of setting the padding\" src=\"https://stuff.charm.sh/vhs/examples/padding.gif\">\n</picture>\n\n#### Set Margin\n\nSet the margin (in pixels) of the video with the `Set Margin` command.\n\n```elixir\nSet Margin 60\nSet MarginFill \"#6B50FF\"\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://vhs.charm.sh/vhs-1miKMtNHenh7O4sv76TMwG.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://vhs.charm.sh/vhs-1miKMtNHenh7O4sv76TMwG.gif\">\n  <img width=\"600\" alt=\"Example of setting the margin\" src=\"https://vhs.charm.sh/vhs-1miKMtNHenh7O4sv76TMwG.gif\">\n</picture>\n\n#### Set Window Bar\n\nSet the type of window bar (Colorful, ColorfulRight, Rings, RingsRight) on the terminal window with the `Set WindowBar` command.\n\n```elixir\nSet WindowBar Colorful\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://vhs.charm.sh/vhs-4VgviCu38DbaGtbRzhtOUI.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://vhs.charm.sh/vhs-4VgviCu38DbaGtbRzhtOUI.gif\">\n  <img width=\"600\" alt=\"Example of setting the margin\" src=\"https://vhs.charm.sh/vhs-4VgviCu38DbaGtbRzhtOUI.gif\">\n</picture>\n\n#### Set Border Radius\n\nSet the border radius (in pixels) of the terminal window with the `Set BorderRadius` command.\n\n```elixir\n# You'll likely want to add a Margin + MarginFill if you use BorderRadius.\nSet Margin 20\nSet MarginFill \"#674EFF\"\nSet BorderRadius 10\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://vhs.charm.sh/vhs-4nYoy6IsUKmleJANG7N1BH.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://vhs.charm.sh/vhs-4nYoy6IsUKmleJANG7N1BH.gif\">\n  <img width=\"400\" alt=\"Example of setting the margin\" src=\"https://vhs.charm.sh/vhs-4nYoy6IsUKmleJANG7N1BH.gif\">\n</picture>\n\n#### Set Framerate\n\nSet the rate at which VHS captures frames with the `Set Framerate` command.\n\n```elixir\nSet Framerate 60\n```\n\n#### Set Playback Speed\n\nSet the playback speed of the final render.\n\n```elixir\nSet PlaybackSpeed 0.5 # Make output 2 times slower\nSet PlaybackSpeed 1.0 # Keep output at normal speed (default)\nSet PlaybackSpeed 2.0 # Make output 2 times faster\n```\n\n#### Set Loop Offset\n\nSet the offset for when the GIF loop should begin. This allows you to make the\nfirst frame of the GIF (generally used for previews) more interesting.\n\n```elixir\nSet LoopOffset 5 # Start the GIF at the 5th frame\nSet LoopOffset 50% # Start the GIF halfway through\n```\n\n#### Set Cursor Blink\n\nSet whether the cursor should blink. Enabled by default.\n\n```elixir\nSet CursorBlink false\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://vhs.charm.sh/vhs-3rMCb80VEkaDdTOJMCrxKy.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://vhs.charm.sh/vhs-3rMCb80VEkaDdTOJMCrxKy.gif\">\n  <img width=\"600\" alt=\"Example of setting the cursor blink.\" src=\"https://vhs.charm.sh/vhs-3rMCb80VEkaDdTOJMCrxKy.gif\">\n</picture>\n\n### Type\n\nUse `Type` to emulate key presses. That is, you can use `Type` to script typing\nin a terminal. Type is handy for both entering commands and interacting with\nprompts and TUIs in the terminal. The command takes a string argument of the\ncharacters to type.\n\nYou can set the standard typing speed with [`Set TypingSpeed`](#set-typing-speed)\nand override it in places with a `@time` argument.\n\n```elixir\n# Type something\nType \"Whatever you want\"\n\n# Type something really slowly!\nType@500ms \"Slow down there, partner.\"\n```\n\nEscape single and double quotes with backticks.\n\n```elixir\nType `VAR=\"Escaped\"`\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/type.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/type.gif\">\n  <img width=\"600\" alt=\"Example of using the Type command in VHS\" src=\"https://stuff.charm.sh/vhs/examples/type.gif\">\n</picture>\n\n### Keys\n\nKey commands take an optional `@time` and optional repeat `count` for repeating\nthe key press every interval of `<time>`.\n\n```\nKey[@<time>] [count]\n```\n\n#### Backspace\n\nPress the backspace key with the `Backspace` command.\n\n```elixir\nBackspace 18\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/backspace.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/backspace.gif\">\n  <img width=\"600\" alt=\"Example of pressing the Backspace key 18 times\" src=\"https://stuff.charm.sh/vhs/examples/backspace.gif\">\n</picture>\n\n#### Ctrl\n\nYou can access the control modifier and send control sequences with the `Ctrl`\ncommand.\n\n```elixir\nCtrl+R\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/ctrl.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/ctrl.gif\">\n  <img width=\"600\" alt=\"Example of pressing the Ctrl+R key to reverse search\" src=\"https://stuff.charm.sh/vhs/examples/ctrl.gif\">\n</picture>\n\n#### Enter\n\nPress the enter key with the `Enter` command.\n\n```elixir\nEnter 2\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/enter.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/enter.gif\">\n  <img width=\"600\" alt=\"Example of pressing the Enter key twice\" src=\"https://stuff.charm.sh/vhs/examples/enter.gif\">\n</picture>\n\n#### Arrow Keys\n\nPress any of the arrow keys with the `Up`, `Down`, `Left`, `Right` commands.\n\n```elixir\nUp 2\nDown 2\nLeft\nRight\nLeft\nRight\nType \"B\"\nType \"A\"\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/arrow.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/arrow.gif\">\n  <img width=\"600\" alt=\"Example of pressing the arrow keys to navigate text\" src=\"https://stuff.charm.sh/vhs/examples/arrow.gif\">\n</picture>\n\n#### Tab\n\nEnter a tab with the `Tab` command.\n\n```elixir\nTab@500ms 2\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/tab.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/tab.gif\">\n  <img width=\"600\" alt=\"Example of pressing the tab key twice for autocomplete\" src=\"https://stuff.charm.sh/vhs/examples/tab.gif\">\n</picture>\n\n#### Space\n\nPress the space bar with the `Space` command.\n\n```elixir\nSpace 10\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/space.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/space.gif\">\n  <img width=\"600\" alt=\"Example of pressing the space key\" src=\"https://stuff.charm.sh/vhs/examples/space.gif\">\n</picture>\n\n#### Page Up / Down\n\nPress the Page Up / Down keys with the `PageUp` or `PageDown` commands.\n\n```elixir\nPageUp 3\nPageDown 5\n```\n\n#### Scroll Up / Down\n\nScroll the terminal viewport directly with `ScrollUp` and `ScrollDown`.\nBoth commands use the same optional `@time` and repeat count shape as other\nrepeatable key commands: `ScrollUp[@<time>] [count]`.\n\n```elixir\nScrollUp 10\nScrollDown 4\nScrollDown@100ms 12\n```\n\n### Wait\n\nThe `Wait` command allows you to wait for something to appear on the screen.\nThis is useful when you need to wait on something to complete, even if you don't\nknow how long it'll take, while including it in the recording like a spinner or\nloading state.\nThe command takes a regular expression as an argument, and optionally allows to\nset the duration to wait and if you want to check the whole screen or just the\nlast line (the scope).\n\n```elixir\nWait\nWait            /World/\nWait+Screen     /World/\nWait+Line       /World/\nWait@10ms       /World/\nWait+Line@10ms  /World/\n```\n\nThe default regular expression is `/>$/`, the wait timeout is `15s`, and the\ndefault scope is `Line`.\n\n### Sleep\n\nThe `Sleep` command allows you to continue capturing frames without interacting\nwith the terminal. This is useful when you need to wait on something to\ncomplete while including it in the recording like a spinner or loading state.\nThe command takes a number argument in seconds.\n\n```elixir\nSleep 0.5   # 500ms\nSleep 2     # 2s\nSleep 100ms # 100ms\nSleep 1s    # 1s\n```\n\n### Hide\n\nThe `Hide` command instructs VHS to stop capturing frames. It's useful to pause\na recording to perform hidden commands.\n\n```elixir\nHide\n```\n\nThis command is helpful for performing any setup and cleanup required to record\na GIF, such as building the latest version of a binary and removing the binary\nonce the demo is recorded.\n\n```elixir\nOutput example.gif\n\n# Setup\nHide\nType \"go build -o example . && clear\"\nEnter\nShow\n\n# Recording...\nType 'Running ./example'\n...\nEnter\n\n# Cleanup\nHide\nType 'rm example'\nEnter\n```\n\n### Show\n\nThe `Show` command instructs VHS to begin capturing frames, again. It's useful\nafter a `Hide` command to resume frame recording for the output.\n\n```elixir\nHide\nType \"You won't see this being typed.\"\nShow\nType \"You will see this being typed.\"\n```\n\n<picture>\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://stuff.charm.sh/vhs/examples/hide.gif\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://stuff.charm.sh/vhs/examples/hide.gif\">\n  <img width=\"600\" alt=\"Example of typing something while hidden\" src=\"https://stuff.charm.sh/vhs/examples/hide.gif\">\n</picture>\n\n### Screenshot\n\nThe `Screenshot` command captures the current frame (png format).\n\n```elixir\n# At any point...\nScreenshot examples/screenshot.png\n```\n\n### Copy / Paste\n\nThe `Copy` and `Paste` copy and paste the string from clipboard.\n\n```elixir\nCopy \"https://github.com/charmbracelet\"\nType \"open \"\nSleep 500ms\nPaste\n```\n\n### Env\n\n`Env` command sets the environment variable via key-value pair.\n\n```elixir\nEnv HELLO \"WORLD\"\n\nType \"echo $HELLO\"\nEnter\nSleep 1s\n```\n\n### Source\n\nThe `source` command allows you to execute commands from another tape.\n\n```elixir\nSource config.tape\n```\n\n---\n\n## Continuous Integration\n\nYou can hook up VHS to your CI pipeline to keep your GIFs up-to-date with\nthe official VHS GitHub Action:\n\n> [⚙️ charmbracelet/vhs-action](https://github.com/charmbracelet/vhs-action)\n\nVHS can also be used for integration testing. Use the `.txt` or `.ascii` output\nto generate golden files. Store these files in a git repository to ensure there\nare no diffs between runs of the tape file.\n\n```elixir\nOutput golden.ascii\n```\n\n## Syntax Highlighting\n\nThere’s a tree-sitter grammar for `.tape` files available for editors that\nsupport syntax highlighting with tree-sitter:\n\n> [🌳 charmbracelet/tree-sitter-vhs](https://github.com/charmbracelet/tree-sitter-vhs)\n\nIt works great with Neovim, Emacs, and so on!\n\n## Contributing\n\nSee [contributing][contribute].\n\n[contribute]: https://github.com/charmbracelet/vhs/contribute\n\n## Feedback\n\nWe’d love to hear your thoughts on this project. Feel free to drop us a note!\n\n- [Twitter](https://twitter.com/charmcli)\n- [The Fediverse](https://mastodon.social/@charmcli)\n- [Discord](https://charm.sh/chat)\n\n## License\n\n[MIT](https://github.com/charmbracelet/vhs/raw/main/LICENSE)\n\n---\n\nPart of [Charm](https://charm.sh).\n\n<a href=\"https://charm.sh/\">\n  <img\n    alt=\"The Charm logo\"\n    width=\"400\"\n    src=\"https://stuff.charm.sh/charm-badge.jpg\"\n  />\n</a>\n\nCharm热爱开源 • Charm loves open source\n"
  },
  {
    "path": "THEMES.md",
    "content": "# Themes\n\n* `3024 Day`\n* `3024 Night`\n* `Aardvark Blue`\n* `Abernathy`\n* `Adventure`\n* `AdventureTime`\n* `Afterglow`\n* `Alabaster`\n* `AlienBlood`\n* `Andromeda`\n* `Apple Classic`\n* `arcoiris`\n* `Argonaut`\n* `Arthur`\n* `AtelierSulphurpool`\n* `Atom`\n* `AtomOneLight`\n* `Aurora`\n* `ayu`\n* `Ayu Mirage`\n* `ayu_light`\n* `Banana Blueberry`\n* `Batman`\n* `Belafonte Day`\n* `Belafonte Night`\n* `BirdsOfParadise`\n* `Blazer`\n* `Blue Matrix`\n* `BlueBerryPie`\n* `BlueDolphin`\n* `BlulocoDark`\n* `BlulocoLight`\n* `Borland`\n* `Breeze`\n* `Bright Lights`\n* `Broadcast`\n* `Brogrammer`\n* `Bubbles`\n* `Builtin Dark`\n* `Builtin Light`\n* `Builtin Pastel Dark`\n* `Builtin Solarized Dark`\n* `Builtin Solarized Light`\n* `Builtin Tango Dark`\n* `Builtin Tango Light`\n* `C64`\n* `Calamity`\n* `Catppuccin Frappe`\n* `Catppuccin Latte`\n* `Catppuccin Macchiato`\n* `Catppuccin Mocha`\n* `catppuccin-frappe`\n* `catppuccin-latte`\n* `catppuccin-macchiato`\n* `catppuccin-mocha`\n* `CGA`\n* `Chalk`\n* `Chalkboard`\n* `ChallengerDeep`\n* `Chester`\n* `Ciapre`\n* `CLRS`\n* `Cobalt Neon`\n* `Cobalt2`\n* `coffee_theme`\n* `Contrast Light`\n* `coolnight`\n* `CrayonPonyFish`\n* `Crystal Violet`\n* `Cyber Cube`\n* `Cyberdyne`\n* `cyberpunk`\n* `CyberPunk2077`\n* `Dark Pastel`\n* `Dark+`\n* `darkermatrix`\n* `darkmatrix`\n* `Darkside`\n* `deep`\n* `Desert`\n* `DimmedMonokai`\n* `Django`\n* `DjangoRebornAgain`\n* `DjangoSmooth`\n* `Doom Peacock`\n* `DoomOne`\n* `DotGov`\n* `Dracula`\n* `Dracula+`\n* `DraculaPlus`\n* `duckbones`\n* `Duotone Dark`\n* `Earthsong`\n* `Elemental`\n* `Elementary`\n* `ENCOM`\n* `Espresso`\n* `Espresso Libre`\n* `Everblush`\n* `Fahrenheit`\n* `Fairyfloss`\n* `Fideloper`\n* `FirefoxDev`\n* `Firewatch`\n* `FishTank`\n* `Flat`\n* `Flatland`\n* `Floraverse`\n* `ForestBlue`\n* `Framer`\n* `FrontEndDelight`\n* `FunForrest`\n* `Galaxy`\n* `Galizur`\n* `Ganyu`\n* `Github`\n* `GitHub Dark`\n* `Glacier`\n* `Glorious`\n* `Grape`\n* `Grass`\n* `Grey-green`\n* `Gruvbox Light`\n* `GruvboxDark`\n* `GruvboxDarkHard`\n* `Guezwhoz`\n* `h4rithd`\n* `h4rithd.com`\n* `Hacktober`\n* `Hardcore`\n* `Harper`\n* `HaX0R_BLUE`\n* `HaX0R_GR33N`\n* `HaX0R_R3D`\n* `Highway`\n* `Hipster Green`\n* `Hivacruz`\n* `Homebrew`\n* `Hopscotch`\n* `Hopscotch.256`\n* `Horizon`\n* `Hurtado`\n* `Hybrid`\n* `Hyper`\n* `IC_Green_PPL`\n* `IC_Orange_PPL`\n* `iceberg-dark`\n* `iceberg-light`\n* `idea`\n* `idleToes`\n* `IR_Black`\n* `iTerm2 Dark Background`\n* `iTerm2 Default`\n* `iTerm2 Light Background`\n* `iTerm2 Pastel Dark Background`\n* `iTerm2 Smoooooth`\n* `iTerm2 Solarized Dark`\n* `iTerm2 Solarized Light`\n* `iTerm2 Tango Dark`\n* `iTerm2 Tango Light`\n* `Jackie Brown`\n* `Japanesque`\n* `Jellybeans`\n* `JetBrains Darcula`\n* `jubi`\n* `Juicy Colors`\n* `Kanagawa`\n* `kanagawabones`\n* `Kibble`\n* `Kolorit`\n* `Konsolas`\n* `Lab Fox`\n* `Laser`\n* `Later This Evening`\n* `Lavandula`\n* `LiquidCarbon`\n* `LiquidCarbonTransparent`\n* `LiquidCarbonTransparentInverse`\n* `lovelace`\n* `Man Page`\n* `Mariana`\n* `Material`\n* `MaterialDark`\n* `MaterialDarker`\n* `MaterialDesignColors`\n* `MaterialOcean`\n* `Mathias`\n* `matrix`\n* `Medallion`\n* `midnight-in-mojave`\n* `Mirage`\n* `Misterioso`\n* `Molokai`\n* `MonaLisa`\n* `Monokai Cmder`\n* `Monokai Pro`\n* `Monokai Pro (Filter Octagon)`\n* `Monokai Pro (Filter Ristretto)`\n* `Monokai Remastered`\n* `Monokai Soda`\n* `Monokai Vivid`\n* `Moonlight II`\n* `N0tch2k`\n* `neobones_dark`\n* `neobones_light`\n* `Neon`\n* `Neopolitan`\n* `Neutron`\n* `Night Owlish Light`\n* `NightLion v1`\n* `NightLion v2`\n* `niji`\n* `Nocturnal Winter`\n* `nord`\n* `nord-light`\n* `Novel`\n* `Obsidian`\n* `Ocean`\n* `Oceanic-Next`\n* `OceanicMaterial`\n* `Ollie`\n* `OneDark`\n* `OneHalfDark`\n* `OneHalfLight`\n* `OneStar`\n* `Operator Mono Dark`\n* `Overnight Slumber`\n* `PaleNightHC`\n* `Pandora`\n* `Paraiso Dark`\n* `PaulMillr`\n* `PencilDark`\n* `PencilLight`\n* `Peppermint`\n* `Piatto Light`\n* `Pnevma`\n* `Popping and Locking`\n* `primary`\n* `Primer`\n* `Pro`\n* `Pro Light`\n* `Purple Rain`\n* `purplepeter`\n* `QB64 Super Dark Blue`\n* `Rapture`\n* `Raycast_Dark`\n* `Raycast_Light`\n* `rebecca`\n* `Red Alert`\n* `Red Planet`\n* `Red Sands`\n* `Relaxed`\n* `Retro`\n* `Retrowave`\n* `Rippedcasts`\n* `Rose Pine`\n* `rose-pine`\n* `rose-pine-dawn`\n* `rose-pine-moon`\n* `Rouge 2`\n* `Royal`\n* `Ryuuko`\n* `Sakura`\n* `Scarlet Protocol`\n* `Seafoam Pastel`\n* `SeaShells`\n* `seoulbones_dark`\n* `seoulbones_light`\n* `Serendipity Midnight`\n* `Serendipity Morning`\n* `Serendipity Sunset`\n* `Seti`\n* `shades-of-purple`\n* `Shaman`\n* `Slate`\n* `SleepyHollow`\n* `Smyck`\n* `Snazzy`\n* `SoftServer`\n* `Solarized Darcula`\n* `Solarized Dark - Patched`\n* `Solarized Dark Higher Contrast`\n* `Sonoran Gothic`\n* `Sonoran Sunrise`\n* `Spacedust`\n* `SpaceGray`\n* `SpaceGray Eighties`\n* `SpaceGray Eighties Dull`\n* `Spiderman`\n* `Spring`\n* `Square`\n* `Sublette`\n* `Subliminal`\n* `Sundried`\n* `Symfonic`\n* `synthwave`\n* `synthwave-everything`\n* `SynthwaveAlpha`\n* `Tango Adapted`\n* `Tango Half Adapted`\n* `Teerb`\n* `Terminal Basic`\n* `Thayer Bright`\n* `The Hulk`\n* `Tinacious Design (Dark)`\n* `Tinacious Design (Light)`\n* `TokyoNight`\n* `tokyonight`\n* `tokyonight-day`\n* `tokyonight-storm`\n* `TokyoNightLight`\n* `TokyoNightStorm`\n* `Tomorrow`\n* `Tomorrow Night`\n* `Tomorrow Night Blue`\n* `Tomorrow Night Bright`\n* `Tomorrow Night Burns`\n* `Tomorrow Night Eighties`\n* `ToyChest`\n* `Treehouse`\n* `Twilight`\n* `Ubuntu`\n* `UltraDark`\n* `UltraViolent`\n* `UnderTheSea`\n* `Unholy`\n* `Unikitty`\n* `Urple`\n* `Vaughn`\n* `VibrantInk`\n* `vimbones`\n* `Violet Dark`\n* `Violet Light`\n* `WarmNeon`\n* `Wez`\n* `Whimsy`\n* `WildCherry`\n* `wilmersdorf`\n* `Wombat`\n* `Wryan`\n* `zenbones`\n* `zenbones_dark`\n* `zenbones_light`\n* `Zenburn`\n* `zenburned`\n* `zenwritten_dark`\n* `zenwritten_light`\n* `Zeonica`\n"
  },
  {
    "path": "command.go",
    "content": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/atotto/clipboard\"\n\t\"github.com/charmbracelet/vhs/parser\"\n\t\"github.com/charmbracelet/vhs/token\"\n\t\"github.com/go-rod/rod/lib/input\"\n)\n\n// Execute executes a command on a running instance of vhs.\nfunc Execute(c parser.Command, v *VHS) error {\n\terr := CommandFuncs[c.Type](c, v)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to execute command: %w\", err)\n\t}\n\n\tif v.recording && v.Options.Test.Output != \"\" {\n\t\terr := v.SaveOutput()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to save output: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// CommandFunc is a function that executes a command on a running\n// instance of vhs.\ntype CommandFunc func(c parser.Command, v *VHS) error\n\n// CommandFuncs maps command types to their executable functions.\nvar CommandFuncs = map[parser.CommandType]CommandFunc{\n\ttoken.BACKSPACE:   ExecuteKey(input.Backspace),\n\ttoken.DELETE:      ExecuteKey(input.Delete),\n\ttoken.INSERT:      ExecuteKey(input.Insert),\n\ttoken.DOWN:        ExecuteKey(input.ArrowDown),\n\ttoken.ENTER:       ExecuteKey(input.Enter),\n\ttoken.LEFT:        ExecuteKey(input.ArrowLeft),\n\ttoken.RIGHT:       ExecuteKey(input.ArrowRight),\n\ttoken.SPACE:       ExecuteKey(input.Space),\n\ttoken.UP:          ExecuteKey(input.ArrowUp),\n\ttoken.TAB:         ExecuteKey(input.Tab),\n\ttoken.ESCAPE:      ExecuteKey(input.Escape),\n\ttoken.PAGE_UP:     ExecuteKey(input.PageUp),\n\ttoken.PAGE_DOWN:   ExecuteKey(input.PageDown),\n\ttoken.SCROLL_UP:   ExecuteScroll(-1),\n\ttoken.SCROLL_DOWN: ExecuteScroll(1),\n\ttoken.HIDE:        ExecuteHide,\n\ttoken.REQUIRE:     ExecuteRequire,\n\ttoken.SHOW:        ExecuteShow,\n\ttoken.SET:         ExecuteSet,\n\ttoken.OUTPUT:      ExecuteOutput,\n\ttoken.SLEEP:       ExecuteSleep,\n\ttoken.TYPE:        ExecuteType,\n\ttoken.CTRL:        ExecuteCtrl,\n\ttoken.ALT:         ExecuteAlt,\n\ttoken.SHIFT:       ExecuteShift,\n\ttoken.ILLEGAL:     ExecuteNoop,\n\ttoken.SCREENSHOT:  ExecuteScreenshot,\n\ttoken.COPY:        ExecuteCopy,\n\ttoken.PASTE:       ExecutePaste,\n\ttoken.ENV:         ExecuteEnv,\n\ttoken.WAIT:        ExecuteWait,\n}\n\n// ExecuteNoop is a no-op command that does nothing.\n// Generally, this is used for Unknown commands when dealing with\n// commands that are not recognized.\nfunc ExecuteNoop(_ parser.Command, _ *VHS) error { return nil }\n\n// ExecuteKey is a higher-order function that returns a CommandFunc to execute\n// a key press for a given key. This is so that the logic for key pressing\n// (since they are repeatable and delayable) can be re-used.\n//\n// i.e. ExecuteKey(input.ArrowDown) would return a CommandFunc that executes\n// the ArrowDown key press.\nfunc ExecuteKey(k input.Key) CommandFunc {\n\treturn func(c parser.Command, v *VHS) error {\n\t\ttypingSpeed, err := time.ParseDuration(c.Options)\n\t\tif err != nil {\n\t\t\ttypingSpeed = v.Options.TypingSpeed\n\t\t}\n\t\trepeat, err := strconv.Atoi(c.Args)\n\t\tif err != nil {\n\t\t\trepeat = 1\n\t\t}\n\t\tfor i := 0; i < repeat; i++ {\n\t\t\terr = v.Page.Keyboard.Type(k)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to type key %c: %w\", k, err)\n\t\t\t}\n\t\t\ttime.Sleep(typingSpeed)\n\t\t}\n\n\t\treturn nil\n\t}\n}\n\n// ExecuteScroll returns a command function that scrolls xterm's viewport.\n//\n// The direction argument is expected to be:\n//\n//\t-1 for ScrollUp\n//\t+1 for ScrollDown\n//\n// Each command repeat applies one viewport row movement with the same timing\n// semantics as other repeatable key-like commands (Options is the per-step\n// delay, Args is repeat count).\n//\n// A caller that wires an unexpected direction (for example 10) will still call\n// xterm's scroll API with that value and produce larger jumps per step.\nfunc ExecuteScroll(direction int) CommandFunc {\n\treturn func(c parser.Command, v *VHS) error {\n\t\ttypingSpeed, err := time.ParseDuration(c.Options)\n\t\tif err != nil {\n\t\t\ttypingSpeed = v.Options.TypingSpeed\n\t\t}\n\t\trepeat, err := strconv.Atoi(c.Args)\n\t\tif err != nil {\n\t\t\trepeat = 1\n\t\t}\n\n\t\tfor i := 0; i < repeat; i++ {\n\t\t\t// ScrollUp/ScrollDown are viewport operations implemented directly via\n\t\t\t// xterm's scroll API.\n\t\t\t_, err = v.Page.Eval(fmt.Sprintf(\"() => term.scrollLines(%d)\", direction))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to scroll viewport: %w\", err)\n\t\t\t}\n\t\t\ttime.Sleep(typingSpeed)\n\t\t}\n\n\t\treturn nil\n\t}\n}\n\n// WaitTick is the amount of time to wait between checking for a match.\nconst WaitTick = 10 * time.Millisecond\n\n// ExecuteWait is a CommandFunc that waits for a regex match for the given amount of time.\nfunc ExecuteWait(c parser.Command, v *VHS) error {\n\tscope, rxStr, ok := strings.Cut(c.Args, \" \")\n\trx := v.Options.WaitPattern\n\tif ok {\n\t\t// This is validated on parse so using MustCompile reduces noise.\n\t\trx = regexp.MustCompile(rxStr)\n\t}\n\n\ttimeout := v.Options.WaitTimeout\n\tif c.Options != \"\" {\n\t\tt, err := time.ParseDuration(c.Options)\n\t\tif err != nil {\n\t\t\t// Shouldn't be possible due to parse validation.\n\t\t\treturn fmt.Errorf(\"failed to parse duration: %w\", err)\n\t\t}\n\t\ttimeout = t\n\t}\n\n\tcheckT := time.NewTicker(WaitTick)\n\tdefer checkT.Stop()\n\ttimeoutT := time.NewTimer(timeout)\n\tdefer timeoutT.Stop()\n\n\tfor {\n\t\tvar last string\n\t\tswitch scope {\n\t\tcase \"Line\":\n\t\t\tline, err := v.CurrentLine()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to get current line: %w\", err)\n\t\t\t}\n\t\t\tlast = line\n\n\t\t\tif rx.MatchString(line) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\tcase \"Screen\":\n\t\t\tlines, err := v.Buffer()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to get buffer: %w\", err)\n\t\t\t}\n\t\t\tlast = strings.Join(lines, \"\\n\")\n\n\t\t\tif rx.MatchString(last) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\tdefault:\n\t\t\t// Should be impossible due to parse validation, but we don't want to\n\t\t\t// hang if it does happen due to a bug.\n\t\t\treturn fmt.Errorf(\"invalid scope %q\", scope)\n\t\t}\n\n\t\tselect {\n\t\tcase <-checkT.C:\n\t\t\tcontinue\n\t\tcase <-timeoutT.C:\n\t\t\treturn fmt.Errorf(\"timeout waiting for %q to match %s; last value was: %s\", c.Args, rx.String(), last)\n\t\t}\n\t}\n}\n\n// ExecuteCtrl is a CommandFunc that presses the argument keys and/or modifiers\n// with the ctrl key held down on the running instance of vhs.\nfunc ExecuteCtrl(c parser.Command, v *VHS) error {\n\t// Create key combination by holding ControlLeft\n\taction := v.Page.KeyActions().Press(input.ControlLeft)\n\tkeys := strings.Split(c.Args, \" \")\n\n\tfor i, key := range keys {\n\t\tvar inputKey *input.Key\n\n\t\tswitch key {\n\t\tcase \"Shift\":\n\t\t\tinputKey = &input.ShiftLeft\n\t\tcase \"Alt\":\n\t\t\tinputKey = &input.AltLeft\n\t\tcase \"Enter\":\n\t\t\tinputKey = &input.Enter\n\t\tcase \"Space\":\n\t\t\tinputKey = &input.Space\n\t\tcase \"Backspace\":\n\t\t\tinputKey = &input.Backspace\n\t\tcase \"Left\":\n\t\t\tinputKey = &input.ArrowLeft\n\t\tcase \"Right\":\n\t\t\tinputKey = &input.ArrowRight\n\t\tcase \"Up\":\n\t\t\tinputKey = &input.ArrowUp\n\t\tcase \"Down\":\n\t\t\tinputKey = &input.ArrowDown\n\t\tdefault:\n\t\t\tr := rune(key[0])\n\t\t\tif k, ok := keymap[r]; ok {\n\t\t\t\tinputKey = &k\n\t\t\t}\n\t\t}\n\n\t\t// Press or hold key in case it's valid\n\t\tif inputKey != nil {\n\t\t\tif i != len(keys)-1 {\n\t\t\t\taction.Press(*inputKey)\n\t\t\t} else {\n\t\t\t\t// Other keys will remain pressed until the combination reaches the end\n\t\t\t\taction.Type(*inputKey)\n\t\t\t}\n\t\t}\n\t}\n\n\terr := action.Do()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to type key %s: %w\", c.Args, err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteAlt is a CommandFunc that presses the argument key with the alt key\n// held down on the running instance of vhs.\nfunc ExecuteAlt(c parser.Command, v *VHS) error {\n\terr := v.Page.Keyboard.Press(input.AltLeft)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to press Alt key: %w\", err)\n\t}\n\tif k, ok := token.Keywords[c.Args]; ok { //nolint:nestif\n\t\tswitch k {\n\t\tcase token.ENTER:\n\t\t\terr = v.Page.Keyboard.Type(input.Enter)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to type Enter key: %w\", err)\n\t\t\t}\n\t\tcase token.TAB:\n\t\t\terr := v.Page.Keyboard.Type(input.Tab)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to type Tab key: %w\", err)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor _, r := range c.Args {\n\t\t\tif k, ok := keymap[r]; ok {\n\t\t\t\terr = v.Page.Keyboard.Type(k)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to type key %c: %w\", r, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\terr = v.Page.Keyboard.Release(input.AltLeft)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to release Alt key: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteShift is a CommandFunc that presses the argument key with the shift\n// key held down on the running instance of vhs.\nfunc ExecuteShift(c parser.Command, v *VHS) error {\n\terr := v.Page.Keyboard.Press(input.ShiftLeft)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to press Shift key: %w\", err)\n\t}\n\n\tif k, ok := token.Keywords[c.Args]; ok { //nolint:nestif\n\t\tswitch k {\n\t\tcase token.ENTER:\n\t\t\terr = v.Page.Keyboard.Type(input.Enter)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to type Enter key: %w\", err)\n\t\t\t}\n\t\tcase token.TAB:\n\t\t\terr = v.Page.Keyboard.Type(input.Tab)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to type Tab key: %w\", err)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor _, r := range c.Args {\n\t\t\tif k, ok := keymap[r]; ok {\n\t\t\t\terr = v.Page.Keyboard.Type(k)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to type key %c: %w\", r, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\terr = v.Page.Keyboard.Release(input.ShiftLeft)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to release Shift key: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteHide is a CommandFunc that starts or stops the recording of the vhs.\nfunc ExecuteHide(_ parser.Command, v *VHS) error {\n\tv.PauseRecording()\n\treturn nil\n}\n\n// ExecuteRequire is a CommandFunc that checks if all the binaries mentioned in the\n// Require command are present. If not, it exits with a non-zero error.\nfunc ExecuteRequire(c parser.Command, _ *VHS) error {\n\t_, err := exec.LookPath(c.Args)\n\treturn err //nolint:wrapcheck\n}\n\n// ExecuteShow is a CommandFunc that resumes the recording of the vhs.\nfunc ExecuteShow(_ parser.Command, v *VHS) error {\n\tv.ResumeRecording()\n\treturn nil\n}\n\n// ExecuteSleep sleeps for the desired time specified through the argument of\n// the Sleep command.\nfunc ExecuteSleep(c parser.Command, _ *VHS) error {\n\tdur, err := time.ParseDuration(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse duration: %w\", err)\n\t}\n\ttime.Sleep(dur)\n\treturn nil\n}\n\n// ExecuteType types the argument string on the running instance of vhs.\nfunc ExecuteType(c parser.Command, v *VHS) error {\n\ttypingSpeed := v.Options.TypingSpeed\n\tif c.Options != \"\" {\n\t\tvar err error\n\t\ttypingSpeed, err = time.ParseDuration(c.Options)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to parse typing speed: %w\", err)\n\t\t}\n\t}\n\tfor _, r := range c.Args {\n\t\tk, ok := keymap[r]\n\t\tif ok {\n\t\t\terr := v.Page.Keyboard.Type(k)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to type key %c: %w\", r, err)\n\t\t\t}\n\t\t} else {\n\t\t\terr := v.Page.MustElement(\"textarea\").Input(string(r))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to input text: %w\", err)\n\t\t\t}\n\n\t\t\tv.Page.MustWaitIdle()\n\t\t}\n\t\ttime.Sleep(typingSpeed)\n\t}\n\n\treturn nil\n}\n\n// ExecuteOutput applies the output on the vhs videos.\nfunc ExecuteOutput(c parser.Command, v *VHS) error {\n\tswitch c.Options {\n\tcase \".mp4\":\n\t\tv.Options.Video.Output.MP4 = c.Args\n\tcase \".test\", \".ascii\", \".txt\":\n\t\tv.Options.Test.Output = c.Args\n\tcase \".png\":\n\t\tv.Options.Video.Output.Frames = c.Args\n\tcase \".webm\":\n\t\tv.Options.Video.Output.WebM = c.Args\n\tdefault:\n\t\tv.Options.Video.Output.GIF = c.Args\n\t}\n\n\treturn nil\n}\n\n// ExecuteCopy copies text to the clipboard.\nfunc ExecuteCopy(c parser.Command, _ *VHS) error {\n\treturn clipboard.WriteAll(c.Args) //nolint:wrapcheck\n}\n\n// ExecuteEnv sets env with given key-value pair.\nfunc ExecuteEnv(c parser.Command, _ *VHS) error {\n\treturn os.Setenv(c.Options, c.Args) //nolint:wrapcheck\n}\n\n// ExecutePaste pastes text from the clipboard.\nfunc ExecutePaste(_ parser.Command, v *VHS) error {\n\tclip, err := clipboard.ReadAll()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read clipboard: %w\", err)\n\t}\n\tfor _, r := range clip {\n\t\tk, ok := keymap[r]\n\t\tif ok {\n\t\t\terr = v.Page.Keyboard.Type(k)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to type key %c: %w\", r, err)\n\t\t\t}\n\t\t} else {\n\t\t\terr = v.Page.MustElement(\"textarea\").Input(string(r))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to input text: %w\", err)\n\t\t\t}\n\t\t\tv.Page.MustWaitIdle()\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Settings maps the Set commands to their respective functions.\nvar Settings = map[string]CommandFunc{\n\t\"FontFamily\":    ExecuteSetFontFamily,\n\t\"FontSize\":      ExecuteSetFontSize,\n\t\"Framerate\":     ExecuteSetFramerate,\n\t\"Height\":        ExecuteSetHeight,\n\t\"LetterSpacing\": ExecuteSetLetterSpacing,\n\t\"LineHeight\":    ExecuteSetLineHeight,\n\t\"PlaybackSpeed\": ExecuteSetPlaybackSpeed,\n\t\"Padding\":       ExecuteSetPadding,\n\t\"Theme\":         ExecuteSetTheme,\n\t\"TypingSpeed\":   ExecuteSetTypingSpeed,\n\t\"Width\":         ExecuteSetWidth,\n\t\"Shell\":         ExecuteSetShell,\n\t\"LoopOffset\":    ExecuteLoopOffset,\n\t\"MarginFill\":    ExecuteSetMarginFill,\n\t\"Margin\":        ExecuteSetMargin,\n\t\"WindowBar\":     ExecuteSetWindowBar,\n\t\"WindowBarSize\": ExecuteSetWindowBarSize,\n\t\"BorderRadius\":  ExecuteSetBorderRadius,\n\t\"WaitPattern\":   ExecuteSetWaitPattern,\n\t\"WaitTimeout\":   ExecuteSetWaitTimeout,\n\t\"CursorBlink\":   ExecuteSetCursorBlink,\n}\n\n// ExecuteSet applies the settings on the running vhs specified by the\n// option and argument pass to the command.\nfunc ExecuteSet(c parser.Command, v *VHS) error {\n\treturn Settings[c.Options](c, v)\n}\n\n// ExecuteSetFontSize applies the font size on the vhs.\nfunc ExecuteSetFontSize(c parser.Command, v *VHS) error {\n\tfontSize, err := strconv.Atoi(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse font size: %w\", err)\n\t}\n\tv.Options.FontSize = fontSize\n\t_, err = v.Page.Eval(fmt.Sprintf(\"() => term.options.fontSize = %d\", fontSize))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set font size: %w\", err)\n\t}\n\n\t// When changing the font size only the canvas dimensions change which are\n\t// scaled back during the render to fit the aspect ration and dimensions.\n\t//\n\t// We need to call term.fit to ensure that everything is resized properly.\n\t_, err = v.Page.Eval(\"term.fit\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to fit terminal: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteSetFontFamily applies the font family on the vhs.\nfunc ExecuteSetFontFamily(c parser.Command, v *VHS) error {\n\tv.Options.FontFamily = c.Args\n\t_, err := v.Page.Eval(fmt.Sprintf(\"() => term.options.fontFamily = '%s'\", withSymbolsFallback(c.Args)))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set font family: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteSetHeight applies the height on the vhs.\nfunc ExecuteSetHeight(c parser.Command, v *VHS) error {\n\theight, err := strconv.Atoi(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse height: %w\", err)\n\t}\n\tv.Options.Video.Style.Height = height\n\n\treturn nil\n}\n\n// ExecuteSetWidth applies the width on the vhs.\nfunc ExecuteSetWidth(c parser.Command, v *VHS) error {\n\twidth, err := strconv.Atoi(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse width: %w\", err)\n\t}\n\tv.Options.Video.Style.Width = width\n\n\treturn nil\n}\n\n// ExecuteSetShell applies the shell on the vhs.\nfunc ExecuteSetShell(c parser.Command, v *VHS) error {\n\ts, ok := Shells[c.Args]\n\tif !ok {\n\t\treturn fmt.Errorf(\"invalid shell %s\", c.Args)\n\t}\n\n\tv.Options.Shell = s\n\treturn nil\n}\n\nconst (\n\tbitSize = 64\n\tbase    = 10\n)\n\n// ExecuteSetLetterSpacing applies letter spacing (also known as tracking) on\n// the vhs.\nfunc ExecuteSetLetterSpacing(c parser.Command, v *VHS) error {\n\tletterSpacing, err := strconv.ParseFloat(c.Args, bitSize)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse letter spacing: %w\", err)\n\t}\n\n\tv.Options.LetterSpacing = letterSpacing\n\t_, err = v.Page.Eval(fmt.Sprintf(\"() => term.options.letterSpacing = %f\", letterSpacing))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set letter spacing: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteSetLineHeight applies the line height on the vhs.\nfunc ExecuteSetLineHeight(c parser.Command, v *VHS) error {\n\tlineHeight, err := strconv.ParseFloat(c.Args, bitSize)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse line height: %w\", err)\n\t}\n\n\tv.Options.LineHeight = lineHeight\n\t_, err = v.Page.Eval(fmt.Sprintf(\"() => term.options.lineHeight = %f\", lineHeight))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set line height: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteSetTheme applies the theme on the vhs.\nfunc ExecuteSetTheme(c parser.Command, v *VHS) error {\n\tvar err error\n\tv.Options.Theme, err = getTheme(c.Args)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tbts, err := json.Marshal(v.Options.Theme)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to marshal theme: %w\", err)\n\t}\n\n\t_, err = v.Page.Eval(fmt.Sprintf(\"() => term.options.theme = %s\", string(bts)))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set theme: %w\", err)\n\t}\n\n\tv.Options.Video.Style.BackgroundColor = v.Options.Theme.Background\n\tv.Options.Video.Style.WindowBarColor = v.Options.Theme.Background\n\n\treturn nil\n}\n\n// ExecuteSetTypingSpeed applies the default typing speed on the vhs.\nfunc ExecuteSetTypingSpeed(c parser.Command, v *VHS) error {\n\ttypingSpeed, err := time.ParseDuration(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse typing speed: %w\", err)\n\t}\n\n\tv.Options.TypingSpeed = typingSpeed\n\treturn nil\n}\n\n// ExecuteSetWaitTimeout applies the default wait timeout on the vhs.\nfunc ExecuteSetWaitTimeout(c parser.Command, v *VHS) error {\n\twaitTimeout, err := time.ParseDuration(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse wait timeout: %w\", err)\n\t}\n\tv.Options.WaitTimeout = waitTimeout\n\treturn nil\n}\n\n// ExecuteSetWaitPattern applies the default wait pattern on the vhs.\nfunc ExecuteSetWaitPattern(c parser.Command, v *VHS) error {\n\trx, err := regexp.Compile(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to compile regexp: %w\", err)\n\t}\n\tv.Options.WaitPattern = rx\n\treturn nil\n}\n\n// ExecuteSetPadding applies the padding on the vhs.\nfunc ExecuteSetPadding(c parser.Command, v *VHS) error {\n\tpadding, err := strconv.Atoi(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse padding: %w\", err)\n\t}\n\n\tv.Options.Video.Style.Padding = padding\n\treturn nil\n}\n\n// ExecuteSetFramerate applies the framerate on the vhs.\nfunc ExecuteSetFramerate(c parser.Command, v *VHS) error {\n\tframerate, err := strconv.ParseInt(c.Args, base, 0)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse framerate: %w\", err)\n\t}\n\n\tv.Options.Video.Framerate = int(framerate)\n\treturn nil\n}\n\n// ExecuteSetPlaybackSpeed applies the playback speed option on the vhs.\nfunc ExecuteSetPlaybackSpeed(c parser.Command, v *VHS) error {\n\tplaybackSpeed, err := strconv.ParseFloat(c.Args, bitSize)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse playback speed: %w\", err)\n\t}\n\n\tv.Options.Video.PlaybackSpeed = playbackSpeed\n\treturn nil\n}\n\n// ExecuteLoopOffset applies the loop offset option on the vhs.\nfunc ExecuteLoopOffset(c parser.Command, v *VHS) error {\n\tloopOffset, err := strconv.ParseFloat(strings.TrimRight(c.Args, \"%\"), bitSize)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse loop offset: %w\", err)\n\t}\n\n\tv.Options.LoopOffset = loopOffset\n\treturn nil\n}\n\n// ExecuteSetMarginFill sets vhs margin fill.\nfunc ExecuteSetMarginFill(c parser.Command, v *VHS) error {\n\tv.Options.Video.Style.MarginFill = c.Args\n\treturn nil\n}\n\n// ExecuteSetMargin sets vhs margin size.\nfunc ExecuteSetMargin(c parser.Command, v *VHS) error {\n\tmargin, err := strconv.Atoi(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse margin: %w\", err)\n\t}\n\n\tv.Options.Video.Style.Margin = margin\n\treturn nil\n}\n\n// ExecuteSetWindowBar sets window bar type.\nfunc ExecuteSetWindowBar(c parser.Command, v *VHS) error {\n\tv.Options.Video.Style.WindowBar = c.Args\n\treturn nil\n}\n\n// ExecuteSetWindowBarSize sets window bar size.\nfunc ExecuteSetWindowBarSize(c parser.Command, v *VHS) error {\n\twindowBarSize, err := strconv.Atoi(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse window bar size: %w\", err)\n\t}\n\n\tv.Options.Video.Style.WindowBarSize = windowBarSize\n\treturn nil\n}\n\n// ExecuteSetBorderRadius sets corner radius.\nfunc ExecuteSetBorderRadius(c parser.Command, v *VHS) error {\n\tborderRadius, err := strconv.Atoi(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse border radius: %w\", err)\n\t}\n\n\tv.Options.Video.Style.BorderRadius = borderRadius\n\treturn nil\n}\n\n// ExecuteSetCursorBlink sets cursor blinking.\nfunc ExecuteSetCursorBlink(c parser.Command, v *VHS) error {\n\tvar err error\n\tv.Options.CursorBlink, err = strconv.ParseBool(c.Args)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse cursor blink: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ExecuteScreenshot is a CommandFunc that indicates a new screenshot must be taken.\nfunc ExecuteScreenshot(c parser.Command, v *VHS) error {\n\tv.ScreenshotNextFrame(c.Args)\n\treturn nil\n}\n\nfunc getTheme(s string) (Theme, error) {\n\tif strings.TrimSpace(s) == \"\" {\n\t\treturn DefaultTheme, nil\n\t}\n\tswitch s[0] {\n\tcase '{':\n\t\treturn getJSONTheme(s)\n\tdefault:\n\t\treturn findTheme(s)\n\t}\n}\n\nfunc getJSONTheme(s string) (Theme, error) {\n\tvar t Theme\n\tif err := json.Unmarshal([]byte(s), &t); err != nil {\n\t\treturn DefaultTheme, fmt.Errorf(\"invalid `Set Theme %q: %w`\", s, err)\n\t}\n\treturn t, nil\n}\n"
  },
  {
    "path": "command_test.go",
    "content": "package main\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/vhs/parser\"\n)\n\nfunc TestCommand(t *testing.T) {\n\tconst numberOfCommands = 31\n\tif len(parser.CommandTypes) != numberOfCommands {\n\t\tt.Errorf(\"Expected %d commands, got %d\", numberOfCommands, len(parser.CommandTypes))\n\t}\n\n\tconst numberOfCommandFuncs = 31\n\tif len(CommandFuncs) != numberOfCommandFuncs {\n\t\tt.Errorf(\"Expected %d commands, got %d\", numberOfCommandFuncs, len(CommandFuncs))\n\t}\n}\n\nfunc TestExecuteSetTheme(t *testing.T) {\n\tt.Run(\"empty\", func(t *testing.T) {\n\t\ttheme, err := getTheme(\"  \")\n\t\trequireNoErr(t, err)\n\t\trequireDefaultTheme(t, theme)\n\t})\n\tt.Run(\"named\", func(t *testing.T) {\n\t\ttheme, err := getTheme(\"Andromeda\")\n\t\trequireNoErr(t, err)\n\t\trequireNotDefaultTheme(t, theme)\n\t})\n\tt.Run(\"json\", func(t *testing.T) {\n\t\ttheme, err := getTheme(`{\"background\": \"#29283b\"}`)\n\t\trequireNoErr(t, err)\n\t\trequireNotDefaultTheme(t, theme)\n\t\tif \"#29283b\" != theme.Background {\n\t\t\tt.Errorf(\"wrong background, expected %q, got %q\", \"#29283b\", theme.Background)\n\t\t}\n\t})\n\tt.Run(\"suggestion\", func(t *testing.T) {\n\t\ttheme, err := getTheme(\"cattppuccin latt\")\n\t\trequireEqualErr(t, err, \"invalid `Set Theme \\\"cattppuccin latt\\\"`: did you mean \\\"Catppuccin Latte\\\"\")\n\t\trequireDefaultTheme(t, theme)\n\t})\n\tt.Run(\"invalid json\", func(t *testing.T) {\n\t\ttheme, err := getTheme(`{\"background`)\n\t\trequireErr(t, err)\n\t\trequireDefaultTheme(t, theme)\n\t})\n\tt.Run(\"unknown theme\", func(t *testing.T) {\n\t\ttheme, err := getTheme(\"foobar\")\n\t\trequireErr(t, err)\n\t\trequireDefaultTheme(t, theme)\n\t})\n}\n\nfunc requireErr(tb testing.TB, err error) {\n\ttb.Helper()\n\tif err == nil {\n\t\ttb.Fatalf(\"expected an error, got nil\")\n\t}\n}\n\nfunc requireEqualErr(tb testing.TB, err1 error, err2 string) {\n\ttb.Helper()\n\tif err1 == nil {\n\t\ttb.Fatalf(\"expected an error, got nil\")\n\t}\n\tif err1.Error() != err2 {\n\t\ttb.Fatalf(\"errors do not match: %q != %q\", err1.Error(), err2)\n\t}\n}\n\nfunc requireNoErr(tb testing.TB, err error) {\n\ttb.Helper()\n\tif err != nil {\n\t\ttb.Fatalf(\"expected no error, got: %v\", err)\n\t}\n}\n\nfunc requireDefaultTheme(tb testing.TB, theme Theme) {\n\ttb.Helper()\n\tif !reflect.DeepEqual(DefaultTheme, theme) {\n\t\ttb.Fatalf(\"expected theme to be the default theme, got something else: %+v\", theme)\n\t}\n}\n\nfunc requireNotDefaultTheme(tb testing.TB, theme Theme) {\n\ttb.Helper()\n\tif reflect.DeepEqual(DefaultTheme, theme) {\n\t\ttb.Fatalf(\"expected theme to be different from the default theme, got the default instead\")\n\t}\n}\n"
  },
  {
    "path": "draw.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"image\"\n\t\"image/color\"\n\t\"image/draw\"\n\t\"image/png\"\n\t\"math\"\n\t\"os\"\n)\n\ntype circle struct {\n\tp image.Point\n\tr int\n}\n\nconst (\n\twhite = 0xFF\n\tblack = 0x17\n)\n\nfunc (c *circle) ColorModel() color.Model {\n\treturn color.AlphaModel\n}\n\nfunc (c *circle) Bounds() image.Rectangle {\n\treturn image.Rect(\n\t\tc.p.X-c.r,\n\t\tc.p.Y-c.r,\n\t\tc.p.X+c.r,\n\t\tc.p.Y+c.r,\n\t)\n}\n\nconst (\n\thalfPixel      = 0.5\n\tdoublingFactor = 2\n)\n\nfunc double(i int) int { return i * doublingFactor }\nfunc half(i int) int   { return i / doublingFactor }\n\nfunc (c *circle) At(x, y int) color.Color {\n\t// Prepare points for circle calculations.\n\t// We subtract 1 from the radius to leave space for\n\t// antialiased pixels.\n\txx := float64(x-c.p.X) + halfPixel\n\tyy := float64(y-c.p.Y) + halfPixel\n\trr := float64(c.r) - 1\n\n\t// The distance from this pixel to the closest point\n\t// in the circle.\n\tdist := math.Sqrt(xx*xx+yy*yy) - rr\n\n\tif dist < 0 {\n\t\t// This pixel is inside the circle\n\t\treturn color.Alpha{white}\n\t} else if dist <= 1 {\n\t\t// This pixel is partly inside the circle\n\t\t// and needs antialiasing\n\t\treturn color.Alpha{\n\t\t\tuint8((1 - dist) * white),\n\t\t}\n\t}\n\n\t// This pixel is outside the circle\n\t// and should be fully transparent\n\treturn color.Alpha{0x00}\n}\n\ntype rect struct {\n\tpa image.Point\n\tpb image.Point\n}\n\nfunc (r *rect) ColorModel() color.Model {\n\treturn color.AlphaModel\n}\n\nfunc (r *rect) Bounds() image.Rectangle {\n\treturn image.Rect(r.pa.X, r.pa.Y, r.pb.X, r.pb.Y)\n}\n\nfunc (r *rect) At(x, y int) color.Color {\n\tif (x >= r.pa.X) &&\n\t\t(x < r.pb.X) &&\n\t\t(y >= r.pa.Y) &&\n\t\t(y < r.pb.Y) {\n\t\treturn color.Alpha{white}\n\t}\n\treturn color.Alpha{0x00}\n}\n\ntype roundedrect struct {\n\tpa     image.Point\n\tpb     image.Point\n\tradius int\n}\n\nfunc (r *roundedrect) ColorModel() color.Model {\n\treturn color.AlphaModel\n}\n\nfunc (r *roundedrect) Bounds() image.Rectangle {\n\treturn image.Rect(r.pa.X, r.pa.Y, r.pb.X, r.pb.Y)\n}\n\nfunc (r *roundedrect) At(x, y int) color.Color {\n\t// Top-left corner\n\tif (x >= r.pa.X) &&\n\t\t(x < r.pa.X+r.radius) &&\n\t\t(y >= r.pa.Y) &&\n\t\t(y < r.pa.Y+r.radius) {\n\t\tc := circle{\n\t\t\timage.Point{\n\t\t\t\tr.radius,\n\t\t\t\tr.radius,\n\t\t\t},\n\t\t\t// Add one to corner radius so that\n\t\t\t// fully-opaque pixels match the rectangle.\n\t\t\t// The outermost pixels of a circle are\n\t\t\t// always antialiased and thus transparent.\n\t\t\tr.radius + 1,\n\t\t}\n\t\treturn c.At(x, y)\n\t}\n\n\t// Top-right corner\n\tif (x >= r.pb.X-r.radius) &&\n\t\t(x < r.pb.X) &&\n\t\t(y >= r.pa.Y) &&\n\t\t(y < r.pa.Y+r.radius) {\n\t\tc := circle{\n\t\t\timage.Point{\n\t\t\t\tr.pb.X - r.radius,\n\t\t\t\tr.radius,\n\t\t\t},\n\t\t\tr.radius + 1,\n\t\t}\n\t\treturn c.At(x, y)\n\t}\n\n\t// Bottom-left corner\n\tif (x >= r.pa.X) &&\n\t\t(x < r.pa.X+r.radius) &&\n\t\t(y >= r.pb.Y-r.radius) &&\n\t\t(y < r.pb.Y) {\n\t\tc := circle{\n\t\t\timage.Point{\n\t\t\t\tr.radius,\n\t\t\t\tr.pb.Y - r.radius,\n\t\t\t},\n\t\t\tr.radius + 1,\n\t\t}\n\t\treturn c.At(x, y)\n\t}\n\n\t// Bottom-right corner\n\tif (x >= r.pb.X-r.radius) &&\n\t\t(x < r.pb.X) &&\n\t\t(y >= r.pb.Y-r.radius) &&\n\t\t(y < r.pb.Y) {\n\t\tc := circle{\n\t\t\timage.Point{\n\t\t\t\tr.pb.X - r.radius,\n\t\t\t\tr.pb.Y - r.radius,\n\t\t\t},\n\t\t\tr.radius + 1,\n\t\t}\n\t\treturn c.At(x, y)\n\t}\n\n\treturn color.Alpha{white}\n}\n\n// MakeBorderRadiusMask a mask to round a terminal's corners.\nfunc MakeBorderRadiusMask(width, height, radius int, targetpng string) {\n\timg := image.NewGray(\n\t\timage.Rectangle{\n\t\t\timage.Point{0, 0},\n\t\t\timage.Point{width, height},\n\t\t},\n\t)\n\n\t// Fill image with black\n\tdraw.DrawMask(\n\t\timg, img.Bounds(), &image.Uniform{color.Gray{0x00}}, image.Point{0, 0},\n\t\t&rect{image.Point{0, 0}, image.Point{width, height}},\n\t\timage.Point{0, 0}, draw.Src,\n\t)\n\n\t// Put mask in white on top\n\tdraw.DrawMask(\n\t\timg, img.Bounds(), &image.Uniform{color.Gray{white}}, image.Point{0, 0},\n\t\t&roundedrect{image.Point{0, 0}, image.Point{width, height}, radius},\n\t\timage.Point{0, 0}, draw.Over,\n\t)\n\n\tf, err := os.Create(targetpng)\n\tif err != nil {\n\t\tfmt.Println(ErrorStyle.Render(\"Could not draw Border Mask: unable to save file.\"))\n\t} else {\n\t\terr = png.Encode(f, img)\n\t}\n\n\tif err != nil {\n\t\tfmt.Println(ErrorStyle.Render(\"Could not draw Border Mask: encoding failed.\"))\n\t}\n}\n\n// MakeWindowBar a window bar and save it to a file.\nfunc MakeWindowBar(termWidth, termHeight int, opts StyleOptions, file string) {\n\tvar err error\n\tswitch opts.WindowBar {\n\tcase \"Colorful\":\n\t\terr = makeColorfulBar(termWidth, termHeight, false, opts, file)\n\tcase \"ColorfulRight\":\n\t\terr = makeColorfulBar(termWidth, termHeight, true, opts, file)\n\tcase \"Rings\":\n\t\terr = makeRingBar(termWidth, termHeight, false, opts, file)\n\tcase \"RingsRight\":\n\t\terr = makeRingBar(termWidth, termHeight, true, opts, file)\n\t}\n\n\tif err != nil {\n\t\tfmt.Println(ErrorStyle.Render(\"Couldn't draw Bar: encoding failed\"))\n\t}\n}\n\nconst (\n\tbarToDotRatio       = 6\n\tbarToDotBorderRatio = 5\n)\n\nfunc makeColorfulBar(termWidth int, termHeight int, isRight bool, opts StyleOptions, targetpng string) error {\n\t// Radius of dots\n\tdotRad := opts.WindowBarSize / barToDotRatio\n\tdotDia := double(dotRad)\n\t// Space between dots and edge\n\tdotGap := half(opts.WindowBarSize - dotDia)\n\t// Space between dot centers\n\tdotSpace := dotDia + opts.WindowBarSize/barToDotRatio\n\n\t// Dimensions of bar image\n\twidth := termWidth\n\theight := termHeight + opts.WindowBarSize\n\n\timg := image.NewRGBA(\n\t\timage.Rectangle{\n\t\t\timage.Point{0, 0},\n\t\t\timage.Point{width, height},\n\t\t},\n\t)\n\n\tbg, _ := parseHexColor(opts.WindowBarColor)\n\tdotA := color.RGBA{white, 0x4F, 0x4D, white}\n\tdotB := color.RGBA{0xFE, 0xBB, 0x00, white}\n\tdotC := color.RGBA{0x00, 0xCC, 0x1D, white}\n\n\tvar pta, ptb, ptc image.Point\n\tif isRight {\n\t\tpta = image.Point{termWidth - (dotGap + dotRad), dotRad + dotGap}\n\t\tptb = image.Point{termWidth - (dotGap + dotRad + dotSpace), dotRad + dotGap}\n\t\tptc = image.Point{termWidth - (dotGap + dotRad + 2*dotSpace), dotRad + dotGap}\n\t} else {\n\t\tpta = image.Point{dotGap + dotRad, dotRad + dotGap}\n\t\tptb = image.Point{dotGap + dotRad + dotSpace, dotRad + dotGap}\n\t\tptc = image.Point{dotGap + dotRad + 2*dotSpace, dotRad + dotGap}\n\t}\n\n\tdraw.DrawMask(\n\t\timg, img.Bounds(), &image.Uniform{bg}, image.Point{0, 0},\n\t\t&rect{image.Point{0, 0}, image.Point{width, height}},\n\t\timage.Point{0, 0}, draw.Src,\n\t)\n\n\tdraw.DrawMask(\n\t\timg,\n\t\timg.Bounds(),\n\t\t&image.Uniform{dotA},\n\t\timage.Point{0, 0},\n\t\t&circle{pta, dotRad},\n\t\timage.Point{0, 0},\n\t\tdraw.Over,\n\t)\n\n\tdraw.DrawMask(\n\t\timg,\n\t\timg.Bounds(),\n\t\t&image.Uniform{dotB},\n\t\timage.Point{0, 0},\n\t\t&circle{ptb, dotRad},\n\t\timage.Point{0, 0},\n\t\tdraw.Over,\n\t)\n\n\tdraw.DrawMask(\n\t\timg,\n\t\timg.Bounds(),\n\t\t&image.Uniform{dotC},\n\t\timage.Point{0, 0},\n\t\t&circle{ptc, dotRad},\n\t\timage.Point{0, 0},\n\t\tdraw.Over,\n\t)\n\n\tf, err := os.Create(targetpng)\n\tif err != nil {\n\t\tfmt.Println(ErrorStyle.Render(\"Couldn't draw colorful bar: unable to save file.\"))\n\t} else {\n\t\terr = png.Encode(f, img)\n\t}\n\treturn err //nolint:wrapcheck\n}\n\nfunc makeRingBar(termWidth int, termHeight int, isRight bool, opts StyleOptions, targetpng string) error {\n\t// Radius of dots\n\touterRad := opts.WindowBarSize / barToDotBorderRatio\n\touterDia := double(outerRad)\n\tinnerRad := double(outerDia) / barToDotBorderRatio\n\t// Space between dots and edge\n\tringGap := half(opts.WindowBarSize - outerDia)\n\t// Space between dot centers\n\tringSpace := outerDia + opts.WindowBarSize/barToDotRatio\n\n\t// Dimensions of bar image\n\twidth := termWidth\n\theight := termHeight + opts.WindowBarSize\n\n\timg := image.NewRGBA(\n\t\timage.Rectangle{\n\t\t\timage.Point{0, 0},\n\t\t\timage.Point{width, height},\n\t\t},\n\t)\n\n\tbg, _ := parseHexColor(opts.WindowBarColor)\n\tring := color.RGBA{0x33, 0x33, 0x33, white}\n\n\tdraw.DrawMask(\n\t\timg, img.Bounds(), &image.Uniform{bg}, image.Point{0, 0},\n\t\t&rect{image.Point{0, 0}, image.Point{width, height}},\n\t\timage.Point{0, 0}, draw.Src,\n\t)\n\n\tfor i := 0; i <= 2; i++ {\n\t\tvar pt image.Point\n\t\tif isRight {\n\t\t\tpt = image.Point{\n\t\t\t\ttermWidth - (ringGap + outerRad + i*ringSpace),\n\t\t\t\touterRad + ringGap,\n\t\t\t}\n\t\t} else {\n\t\t\tpt = image.Point{\n\t\t\t\tringGap + outerRad + i*ringSpace,\n\t\t\t\touterRad + ringGap,\n\t\t\t}\n\t\t}\n\n\t\tdraw.DrawMask(\n\t\t\timg,\n\t\t\timg.Bounds(),\n\t\t\t&image.Uniform{ring},\n\t\t\timage.Point{0, 0},\n\t\t\t&circle{pt, outerRad},\n\t\t\timage.Point{0, 0},\n\t\t\tdraw.Over,\n\t\t)\n\n\t\tdraw.DrawMask(\n\t\t\timg,\n\t\t\timg.Bounds(),\n\t\t\t&image.Uniform{bg},\n\t\t\timage.Point{0, 0},\n\t\t\t&circle{pt, innerRad},\n\t\t\timage.Point{0, 0},\n\t\t\tdraw.Over,\n\t\t)\n\t}\n\n\tf, err := os.Create(targetpng)\n\tif err != nil {\n\t\tfmt.Println(ErrorStyle.Render(\"Couldn't draw ring bar: unable to save file.\"))\n\t} else {\n\t\terr = png.Encode(f, img)\n\t}\n\treturn err //nolint:wrapcheck\n}\n\n//nolint:mnd\nfunc parseHexColor(s string) (c color.RGBA, err error) {\n\tc.R, c.G, c.B, c.A = black, black, black, white\n\tswitch len(s) {\n\tcase 7:\n\t\t_, err = fmt.Sscanf(s, \"#%02x%02x%02x\", &c.R, &c.G, &c.B)\n\tcase 6:\n\t\t_, err = fmt.Sscanf(s, \"%02x%02x%02x\", &c.R, &c.G, &c.B)\n\tcase 4:\n\t\t_, err = fmt.Sscanf(s, \"#%1x%1x%1x\", &c.R, &c.G, &c.B)\n\t\t// Double the hex digits:\n\t\tc.R *= 17\n\t\tc.G *= 17\n\t\tc.B *= 17\n\tcase 3:\n\t\t_, err = fmt.Sscanf(s, \"%1x%1x%1x\", &c.R, &c.G, &c.B)\n\t\t// Double the hex digits:\n\t\tc.R *= 17\n\t\tc.G *= 17\n\t\tc.B *= 17\n\tdefault:\n\t\terr = fmt.Errorf(\"%s color of invalid length\", s)\n\t}\n\treturn\n}\n"
  },
  {
    "path": "embed.go",
    "content": "package main\n\nimport _ \"embed\"\n\n//go:embed examples/demo.tape\nvar demoTape []byte\n"
  },
  {
    "path": "error.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/vhs/parser\"\n)\n\n// InvalidSyntaxError is returned when the parser encounters one or more errors.\ntype InvalidSyntaxError struct {\n\tErrors []parser.Error\n}\n\nfunc (e InvalidSyntaxError) Error() string {\n\treturn fmt.Sprintf(\"parser: %d error(s)\", len(e.Errors))\n}\n\n// ErrorColumnOffset is the number of columns that an error should be printed\n// to the left to account for the line number.\nconst ErrorColumnOffset = 5\n\n// Underline returns a string of ^ characters which helps underline the problematic token\n// in a parser.Error.\nfunc Underline(n int) string {\n\treturn ErrorStyle.Render(strings.Repeat(\"^\", n))\n}\n\n// LineNumber returns a formatted version of the given line number.\nfunc LineNumber(line int) string {\n\treturn LineNumberStyle.Render(fmt.Sprintf(\" %2d │ \", line))\n}\n\nfunc printError(out io.Writer, tape string, err parser.Error) {\n\tlines := strings.Split(tape, \"\\n\")\n\n\t_, _ = fmt.Fprint(out, LineNumber(err.Token.Line))\n\t_, _ = fmt.Fprintln(out, lines[err.Token.Line-1])\n\t_, _ = fmt.Fprint(out, strings.Repeat(\" \", err.Token.Column+ErrorColumnOffset))\n\t_, _ = fmt.Fprintln(out, Underline(len(err.Token.Literal)), err.Msg)\n\t_, _ = fmt.Fprintln(out)\n}\n\nfunc printErrors(out io.Writer, tape string, errs []error) {\n\tfor _, err := range errs {\n\t\tswitch err := err.(type) {\n\t\tcase InvalidSyntaxError:\n\t\t\tfor _, v := range err.Errors {\n\t\t\t\tprintError(out, tape, v)\n\t\t\t}\n\t\t\t_, _ = fmt.Fprintln(out, ErrorStyle.Render(err.Error()))\n\n\t\tdefault:\n\t\t\t_, _ = fmt.Fprintln(out, ErrorStyle.Render(err.Error()))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "evaluator.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com/charmbracelet/vhs/lexer\"\n\t\"github.com/charmbracelet/vhs/parser\"\n\t\"github.com/charmbracelet/vhs/token\"\n\t\"github.com/go-rod/rod\"\n)\n\n// EvaluatorOption is a function that can be used to modify the VHS instance.\ntype EvaluatorOption func(*VHS)\n\n// Evaluate takes as input a tape string, an output writer, and an output file\n// and evaluates all the commands within the tape string and produces a GIF.\nfunc Evaluate(ctx context.Context, tape string, out io.Writer, opts ...EvaluatorOption) []error {\n\tl := lexer.New(tape)\n\tp := parser.New(l)\n\n\tcmds := p.Parse()\n\terrs := p.Errors()\n\tif len(errs) != 0 || len(cmds) == 0 {\n\t\treturn []error{InvalidSyntaxError{errs}}\n\t}\n\n\tv := New()\n\tfor _, cmd := range cmds {\n\t\tif cmd.Type == token.SET && cmd.Options == \"Shell\" || cmd.Type == token.ENV {\n\t\t\terr := Execute(cmd, &v)\n\t\t\tif err != nil {\n\t\t\t\treturn []error{err}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Start things up\n\tif err := v.Start(); err != nil {\n\t\treturn []error{err}\n\t}\n\tdefer func() { _ = v.close() }()\n\n\t// Let's wait until we can access the window.term variable.\n\t//\n\t// This is necessary because some SET commands modify the terminal.\n\terr := v.Page.Wait(rod.Eval(\"() => window.term != undefined\"))\n\tif err != nil {\n\t\treturn []error{err}\n\t}\n\n\tvar offset int\n\tfor i, cmd := range cmds {\n\t\tif cmd.Type == token.SET || cmd.Type == token.OUTPUT || cmd.Type == token.REQUIRE {\n\t\t\t_, _ = fmt.Fprintln(out, Highlight(cmd, false))\n\t\t\tif cmd.Options != \"Shell\" {\n\t\t\t\terr := Execute(cmd, &v)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn []error{err}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\toffset = i\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Make sure image is big enough to fit padding, bar, and margins\n\tvideo := v.Options.Video\n\tminWidth := double(video.Style.Padding) + double(video.Style.Margin)\n\tminHeight := double(video.Style.Padding) + double(video.Style.Margin)\n\tif video.Style.WindowBar != \"\" {\n\t\tminHeight += video.Style.WindowBarSize\n\t}\n\tif video.Style.Height < minHeight || video.Style.Width < minWidth {\n\t\t//nolint:staticcheck\n\t\tv.Errors = append(\n\t\t\tv.Errors,\n\t\t\tfmt.Errorf(\n\t\t\t\t\"Dimensions must be at least %d x %d\",\n\t\t\t\tminWidth, minHeight,\n\t\t\t),\n\t\t)\n\t}\n\n\tif len(v.Errors) > 0 {\n\t\treturn v.Errors\n\t}\n\n\t// Setup the terminal session so we can start executing commands.\n\tv.Setup()\n\n\t// If the first command (after Settings and Outputs) is a Hide command, we can\n\t// begin executing the commands before we start recording to avoid capturing\n\t// any unwanted frames.\n\tif cmds[offset].Type == token.HIDE {\n\t\tfor i, cmd := range cmds[offset:] {\n\t\t\tif cmd.Type == token.SHOW {\n\t\t\t\toffset += i\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t_, _ = fmt.Fprintln(out, Highlight(cmd, true))\n\t\t\terr := Execute(cmd, &v)\n\t\t\tif err != nil {\n\t\t\t\treturn []error{err}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Begin recording frames as we are now in a recording state.\n\tctx, cancel := context.WithCancel(ctx) //nolint:gosec\n\tch := v.Record(ctx)\n\n\t// Clean up temporary files at the end.\n\tdefer func() {\n\t\tif v.Options.Video.Output.Frames != \"\" {\n\t\t\t// Move the frames to the output directory.\n\t\t\t_ = os.Rename(v.Options.Video.Input, v.Options.Video.Output.Frames)\n\t\t}\n\n\t\t_ = v.Cleanup()\n\t}()\n\n\tteardown := func() {\n\t\t// Stop recording frames.\n\t\tcancel()\n\t\t// Read from channel to ensure recorder is done.\n\t\t<-ch\n\t}\n\n\t// Log errors from the recording process.\n\tgo func() {\n\t\tfor err := range ch {\n\t\t\tlog.Print(err.Error())\n\t\t}\n\t}()\n\n\tfor _, cmd := range cmds[offset:] {\n\t\tif ctx.Err() != nil {\n\t\t\tteardown()\n\t\t\treturn []error{ctx.Err()}\n\t\t}\n\n\t\t// When changing the FontFamily, FontSize, LineHeight, Padding\n\t\t// The xterm.js canvas changes dimensions and causes FFMPEG to not work\n\t\t// correctly (specifically) with palettegen.\n\t\t// It will be possible to change settings on the fly in the future, but\n\t\t// it is currently not as it does not result in a proper render of the\n\t\t// GIF as the frame sequence will change dimensions. This is fixable.\n\t\t//\n\t\t// We should remove if isSetting statement.\n\t\tisSetting := cmd.Type == token.SET && cmd.Options != \"TypingSpeed\"\n\n\t\tif isSetting {\n\t\t\tfmt.Println(ErrorStyle.Render(fmt.Sprintf(\"WARN: 'Set %s %s' has been ignored. Move the directive to the top of the file.\\nLearn more: https://github.com/charmbracelet/vhs#settings\", cmd.Options, cmd.Args)))\n\t\t}\n\t\tif isSetting || cmd.Type == token.REQUIRE {\n\t\t\t_, _ = fmt.Fprintln(out, Highlight(cmd, true))\n\t\t\tcontinue\n\t\t}\n\t\t_, _ = fmt.Fprintln(out, Highlight(cmd, !v.recording || cmd.Type == token.SHOW || cmd.Type == token.HIDE || isSetting))\n\t\terr := Execute(cmd, &v)\n\t\tif err != nil {\n\t\t\tteardown()\n\t\t\treturn []error{err}\n\t\t}\n\t}\n\n\t// If running as an SSH server, the output file is a temporary file\n\t// to use for the output.\n\t//\n\t// We need to set the GIF file path before it is created but after all of\n\t// the settings and commands are executed. This is done in `serve.go`.\n\t//\n\t// Since the GIF creation is deferred, setting the output file here will\n\t// achieve what we want.\n\tfor _, opt := range opts {\n\t\topt(&v)\n\t}\n\n\tteardown()\n\tif err := v.Render(); err != nil {\n\t\treturn []error{err}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "examples/README.md",
    "content": "# Examples\n\n### Gum\n\nExample of recording a demo of [Gum](https://github.com/charmbracelet/gum)\nwith VHS.\n\n#### Gum File\n\n<img alt=\"gum file demo with VHS\" src=\"./gum/file.gif\" width=\"600\" />\n\n```\nOutput file.gif\n\nType \"gum file ./src\"\nSleep 1s\nEnter\nSleep 2s\nDown@500ms 4\nUp@500ms 1\nSleep 1s\nEnter\nSleep 1s\nDown@500ms 4\nSleep 1s\nUp@500ms 2\nSleep 2s\n```\n\n#### Gum Pager\n\n<img alt=\"gum pager demo with VHS\" src=\"./gum/pager.gif\" width=\"600\" />\n\n```\nOutput pager.gif\n\nSet Padding 20\nSet FontSize 16\nSet Height 600\n\nType \"gum pager < ~/src/gum/README.md --border normal\"\nSleep 1s\nEnter\nSleep 2s\nDown@25ms 40\nSleep 1s\nUp@25ms 30\nSleep 1s\nDown@25ms 20\nSleep 3s\n```\n\n#### Gum Table\n\n<img alt=\"gum table demo with VHS\" src=\"./gum/table.gif\" width=\"600\" />\n\n```\nOutput table.gif\n\nType \"gum table < superhero.csv -w 2,12,5,6,6,8,4,20 --height 10\"\nEnter\nSleep 1s\nDown@200ms 10\nSleep 1s\nDown@200ms 10\nSleep 1s\nUp@200ms 10\nSleep 1s\nEnter\nSleep 3s\n```\n\n### GitHub CLI\n\nExamples recorded with VHS for the GitHub CLI (`gh`):\n\n#### Issues\n\n<img alt=\"Simple gh issue demo\" src=\"./gh-cli/gh-issue.gif\" width=\"600\" />\n\n\n```\nOutput gh-issue.gif\n\nType \"gh issue list\"\nSleep 500ms\nEnter 1\nSleep 4s\n\nCtrl+L\nSleep 500ms\n\nType \"gh issue view 19\"\nSleep 500ms\nEnter\n\nSleep 5s\n```\n\n#### Pull Requests\n\n<img alt=\"Simple gh pr demo\" src=\"./gh-cli/gh-pr.gif\" width=\"600\" />\n\n```\nOutput gh-pr.gif\n\nType \"gh pr list --state all\"\nSleep 500ms\nEnter\n\nSleep 5s\n```\n\n### Bubble Tea\n\nExamples recorded with VHS for Bubble Tea.\n\n* [GIFS Renders](https://github.com/charmbracelet/bubbletea/tree/master/examples)\n* [Tape Files](./bubbletea)\n\n### jqp\n\nExample of recording a demo of [`jqp`](https://github.com/noahgorstein/jqp)\nwith VHS.\n\n<img alt=\"Simple jqp demo with VHS\" src=\"./jqp/jqp.gif\" width=\"600\" />\n\n### Glow\n\nExample of recording a demo of [Glow](https://github.com/charmbracelet/glow)\nwith VHS.\n\n#### Glow Simple\n\n<img alt=\"Simple glow demo with VHS\" src=\"./glow/glow-simple.gif\" width=\"600\" />\n\n```\nOutput glow-simple.ascii\nOutput glow-simple.gif\n\nSet Width 1000\nSet Height 1000\n\nType \"glow\"\nEnter\nSleep 1s\nEnter\nSleep 1s\nEscape\nSleep 1s\nType \"q\"\nSleep 1s\n```\n\n#### Glow\n\n<img alt=\"Glow demo with VHS\" src=\"./glow/vhs-glow.gif\" />\n\n```\nOutput vhs-glow.gif\nOutput glow.ascii\n\nSet Width 1600\nSet Height 1040\n\nSleep 1s\n\nType \"glow\"\n\nSleep 100ms\n\nEnter\n\nSleep 1s\n\nHide\nTab\nType \"/artichoke\"\nEnter\nDown 2\nShow\n\nSleep 0.5s\n\nDown 20\n\nHide\nEscape\nType \"l\"\nDown 5\nShow\n\nSleep 1s\nUp@400ms 5\n\nHide\nType \"/ulysses\"\nEnter\nShow\n\nSleep 0.5s\n\nDown@200ms 20\n\nHide\nEscape\nType \"/\"\nShow\n\nSleep 0.5s\n\nType@500ms \"todo\"\nSleep 1\n\nHide\nEscape\nType \"/ulysses\"\nEnter\nShow\n\nSleep 0.5s\n\nType@750ms \"????\"\n\nHide\nEscape\nType \"/artichoke\"\nEnter\nType \"m\"\nCtrl+A\nRight 4\nShow\n\nSleep 1s\nType@250ms \"Tasty \"\nSleep 1s\n\nHide\nEscape\nDown 5\nType \"m\"\nCtrl+U\nShow\n\nSleep 1s\nType@150ms \"Your new internet thing\"\nSleep 3s\n\nHide\nCtrl+C\nShow\n```\n"
  },
  {
    "path": "examples/bubbletea/altscreen-toggle.tape",
    "content": "Output examples/bubbletea/altscreen-toggle.gif\n\nHide\nType \"go build -o altscreen-toggle .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./altscreen-toggle\"\nEnter\nSleep 0.5\nSpace@0.5 4\n\nType \"q\"\nSleep 1\n\nHide\nType \"rm ./altscreen-toggle\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/chat.tape",
    "content": "Output examples/bubbletea/chat.gif\n\nHide\nType \"go build -o chat .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./chat\"\nEnter\nSleep 0.5\nType \"Hello, Chat Room\" Sleep .25\nEnter\nSleep 0.5\nType \"!!!\" Sleep .25\nEnter\nSleep 1\n\nHide\nCtrl+C\nType \"rm chat\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/composable-views.tape",
    "content": "Output examples/bubbletea/composable-views.gif\n\nHide\nType \"go build -o views .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./views\"\nEnter\nSleep 0.5\nTab@1 4\nSleep 0.5\nType \"n\"\nTab\nSleep 0.5\nType@250ms \"nnnn\"\nSleep 1\n\nHide\nCtrl+C\nType \"rm views\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/credit-card-form.tape",
    "content": "Output examples/bubbletea/credit-card-form.gif\n\nHide\nType \"go build -o credit-card .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./credit-card\"\nEnter\nSleep 0.5\n\nType \"1234 5678 9012 3456\"\nSleep .3 Tab Sleep .3\nType \"12/34\"\nSleep .3 Tab Sleep .3\nType \"123\"\nSleep 1\n\nHide\nCtrl+C\nType \"rm credit-card\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/debounce.tape",
    "content": "Output examples/bubbletea/debounce.gif\n\nHide\nType \"go build -o debounce .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./debounce\"\nEnter\nSleep 0.5\n\nSpace@250ms 10\nSleep 1\n\nHide\nCtrl+C\nType \"rm debounce\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/exec.tape",
    "content": "Output examples/bubbletea/exec.gif\n\nHide\nType \"go build -o exec .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"EDITOR=nano ./exec\"\nEnter\nSleep 0.5\n\nType@0.5 \"aaaa\"\nSleep 1\n\nType@0.5 \"e\"\nType \"Hello, EDITOR!\"\nSleep 1\nCtrl+X\nSleep 0.5\nType \"n\"\nSleep 1\n\nHide\nType \"q\"\nType \"rm exec\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/fullscreen.tape",
    "content": "Output examples/bubbletea/fullscreen.gif\n\nHide\nType \"go build -o fullscreen .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./fullscreen\"\nSleep 0.5\nEnter\n\nSleep 4\n\nHide\nType \"rm fullscreen\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/glamour.tape",
    "content": "Output examples/bubbletea/glamour.gif\nSet Height 750\nSet FontSize 16\n\nHide\nType \"go build -o glamour .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./glamour\"\nEnter\nSleep 1\n\nDown@10ms 25\n\nSleep 1\n\nHide\nType \"q\"\nType \"rm glamour\"\nEnter\nShow\n"
  },
  {
    "path": "examples/bubbletea/help.tape",
    "content": "Output examples/bubbletea/help.gif\n\nHide\nType \"go build -o help .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./help\"\nEnter\nSleep 0.5\n\nType@1 \"?\"\n\nUp@0.5\nDown@0.5\nLeft@0.5\nRight@0.5\n\nType@1 \"?\"\n\nType \"q\"\n\nSleep 1\n\nHide\nType \"rm help\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/http.tape",
    "content": "Output examples/bubbletea/http.gif\n\nHide\nType \"go build -o http .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./http\"\nEnter\nSleep 2\n\nHide\nCtrl+C\nType \"rm http\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/list-default.tape",
    "content": "Output examples/bubbletea/list-default.gif\nSet FontSize 16\n\nHide\nType \"go build -o list-default .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./list-default\"\nEnter\nSleep 0.5\n\nDown@250ms 3\nRight@250ms 3\n\nType \"/\"\nSleep 0.5\n\nType \"nutel\"\nEnter\nSleep 0.5\nType \"?\"\nSleep 0.5\nType \"?\"\nSleep 0.5\nEscape@250ms 2\n\nHide\nCtrl+C\nType \"rm list-default\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/list-fancy.tape",
    "content": "Output examples/bubbletea/list-fancy.gif\nSet FontSize 14\n\nHide\nType \"go build -o list-fancy .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./list-fancy\"\nEnter\nSleep 0.5\n\nDown@250ms 3\nEnter\nSleep 0.5\nType \"x\"\nSleep 0.5\nType \"?\"\nSleep 0.5\nType@150ms \"aaaa\"\nType@150ms \"xxxx\"\n\nHide\nCtrl+C\nType \"rm list-fancy\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/list-simple.tape",
    "content": "Output examples/bubbletea/list-simple.gif\nSet FontSize 18\n\nHide\nType \"go build -o list-simple .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./list-simple\"\nEnter\nSleep 0.5\n\nDown@250ms 3\nEnter\nSleep 1\n\nHide\nCtrl+C\nType \"rm list-simple\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/package-manager.tape",
    "content": "Output examples/bubbletea/package-manager.gif\n\nHide\nType \"go build -o package-manager .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./package-manager\"\nEnter\nSleep 0.5\n\nSleep 10\n\nHide\nCtrl+C\nType \"rm package-manager\"\nEnter\nShow\n"
  },
  {
    "path": "examples/bubbletea/pager.tape",
    "content": "Output examples/bubbletea/pager.gif\nSet FontSize 16\n\nHide\nType \"go build -o pager .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./pager\"\nEnter\nSleep 0.5\n\nDown@25ms 20\n\nHide\nType \"q\"\nType \"rm pager\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/paginator.tape",
    "content": "Output examples/bubbletea/paginator.gif\nSet FontSize 12\nSet Padding 36\n\nHide\nType \"go build -o paginator .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./paginator\"\nEnter\nSleep 1\n\nRight@250ms 10\nSleep 1\nLeft@250ms 10\nSleep 1\n\nHide\nCtrl+C\nType \"rm paginator\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/pipe.tape",
    "content": "Output examples/bubbletea/pipe.gif\n\nHide\nType \"go build -o pipe . && clear\"\nEnter\nShow\n\nType \"echo 'Hello' | ./pipe\"\nEnter\nSleep 1\n\nType \", world!\"\nSleep 0.5\nEnter\nSleep 1\n\nHide\nCtrl+C\nType \"rm pipe\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/progress-animated.tape",
    "content": "Output examples/bubbletea/progress-animated.gif\n\nHide\nType \"go build -o progress-animated .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./progress-animated\"\nEnter\nSleep 1\n\nSleep 5\n\nHide\nCtrl+C\nType \"rm progress-animated\"\nEnter\nShow\n"
  },
  {
    "path": "examples/bubbletea/progress-static.tape",
    "content": "Output examples/bubbletea/progress-static.gif\n\nHide\nType \"go build -o progress-static .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./progress-static\"\nEnter\n\nSleep 5\n\nHide\nCtrl+C\nType \"rm progress-static\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/realtime.tape",
    "content": "Output examples/bubbletea/realtime.gif\n\nHide\nType \"go build -o realtime .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./realtime\"\nEnter\nSleep 0.5\n\nSleep 2\nSpace # Exit\nSleep 1\n\nHide\nCtrl+C\nType \"rm realtime\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/result.tape",
    "content": "Output examples/bubbletea/result.gif\n\nHide\nType \"go build -o result .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./result\"\nEnter\nSleep 0.5\n\nDown@250ms 2\nUp@250ms 2\nEnter\nSleep 1\n\nHide\nCtrl+C\nType \"rm result\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/send-msg.tape",
    "content": "Output examples/bubbletea/send-msg.gif\n\nHide\nType \"go build -o send-msg .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./send-msg\"\nEnter\nSleep 3\nSpace\nSleep 1\n\nHide\nCtrl+C\nType \"rm send-msg\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/sequence.tape",
    "content": "Output examples/bubbletea/sequence.gif\n\nHide\nType \"go build -o sequence .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./sequence\"\nEnter\n\nSleep 3\n\nHide\nCtrl+C\nType \"rm sequence\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/simple.tape",
    "content": "Output examples/bubbletea/simple.gif\n\nHide\nType \"go build -o simple .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./simple\"\nEnter\nSleep 0.5\n\nSleep 3\n\nHide\nCtrl+C\nType \"rm simple\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/spinner.tape",
    "content": "Output examples/bubbletea/spinner.gif\n\nHide\nType \"go build -o spinner .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./spinner\"\nEnter\nSleep 0.5\n\nSleep 3\nType \"q\"\nSleep 0.5\n\nHide\nCtrl+C\nType \"rm spinner\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/spinners.tape",
    "content": "Output examples/bubbletea/spinners.gif\n\nHide\nType \"go build -o spinners .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./spinners\"\nEnter\nSleep 3\nRight@1 5\nSleep 1\n\nHide\nCtrl+C\nType \"rm spinners\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/split-editors.tape",
    "content": "Output examples/bubbletea/split-editors.gif\nSet FontSize 16\n\nHide\nType \"go build -o split-editors .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./split-editors\"\nEnter\nSleep 1\n\nType \"Hello, there!\"\nSleep 0.5\nTab\nSleep 0.5\nType \"Hi!\"\nSleep 0.5\nEnter\nType \"How are you?\"\nSleep 0.5\nTab\nSleep 0.5\nCtrl+U\nSleep 0.5\nType \"I'm good! Thanks for asking :)\"\nSleep .5\nEnter\nSleep 0.5\nCtrl+N\nSleep 0.5\nTab@250ms 2\nType \"Hello, world!\"\nSleep 1\n\nHide\nEscape\nType \"rm split-editors\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/stopwatch.tape",
    "content": "Output examples/bubbletea/stopwatch.gif\n\nHide\nType \"go build -o stopwatch .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./stopwatch\"\nEnter\nSleep 0.5\n\nSleep 1\nType \"s\"\nSleep 0.5\nType \"r\"\nSleep 0.5\nType \"s\"\nSleep 2\nType \"q\"\nSleep 0.5\n\nHide\nCtrl+C\nType \"rm stopwatch\"\nEnter\nShow\n"
  },
  {
    "path": "examples/bubbletea/table.tape",
    "content": "Output examples/bubbletea/table.gif\n\nHide\nType \"go build -o table .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./table\"\nEnter\nSleep 0.5\n\nDown@250ms 4\nSleep 1\nEnter\nSleep 1\n\nHide\nCtrl+C\nType \"rm table\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/tabs.tape",
    "content": "Output examples/bubbletea/tabs.gif\n\nHide\nType \"go build -o tabs .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./tabs\"\nEnter\nSleep 0.5\n\nRight@0.5 5\nLeft@0.5 5\nSleep 1\n\nHide\nCtrl+C\nType \"rm tabs\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/textarea.tape",
    "content": "Output examples/bubbletea/textarea.gif\n\nHide\nType \"go build -o textarea .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./textarea\"\nEnter\nSleep 0.5\n\nType \"Makin' my way downtown\"\nSleep 250ms\nEnter\nType \"Walking fast, faces pass\"\nSleep 250ms\nEnter\nType \"And I'm homebound\"\nSleep 1\nCtrl+C\nSleep 1\n\nHide\nType \"rm textarea\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/textinput.tape",
    "content": "Output examples/bubbletea/textinput.gif\n\nHide\nType \"go build -o textinput .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./textinput\"\nEnter\nSleep 0.5\n\nType \"Ponyta\"\nSleep 0.5\nLeft@100ms 2\nType \"(lalala)\"\nSleep 1\n\nHide\nCtrl+C\nType \"rm textinput\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/textinputs.tape",
    "content": "Output examples/bubbletea/textinputs.gif\n\nHide\nType \"go build -o textinputs .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./textinputs\"\nEnter\nSleep 0.5\n\nType \"qt314\"\nSleep 0.5\nTab\nSleep 0.5\nCtrl+R\nSleep 0.5\nType \"pi@cute.com\"\nSleep 0.5\nCtrl+R\nTab\nSleep 0.5\nType \"password\"\n\nHide\nCtrl+C\nType \"rm textinputs\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/timer.tape",
    "content": "Output examples/bubbletea/timer.gif\n\nHide\nType \"go build -o timer .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./timer\"\nSleep 0.5\nEnter\nSleep 0.5\nType \"s\"\nSleep 0.5\nType \"s\"\nSleep 2\n\nHide\nCtrl+C\nType \"rm timer\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/tui-daemon-combo.tape",
    "content": "Output examples/bubbletea/tui-daemon-combo.gif\n\nHide\nType \"go build -o tui-daemon-combo .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./tui-daemon-combo\"\nEnter\nSleep 0.5\n\nSleep 3\nSpace\nSleep 1\n\nHide\nCtrl+C\nType \"rm tui-daemon-combo\"\nEnter\n"
  },
  {
    "path": "examples/bubbletea/views.tape",
    "content": "Output examples/bubbletea/views.gif\n\nHide\nType \"go build -o views .\"\nEnter\nType \"clear\"\nEnter\nShow\n\nType \"./views\"\nEnter\nSleep 1\n\nDown@0.5 2\nSleep 0.5\nEnter\nSleep 3\n\nHide\nCtrl+C\nType \"rm views\"\nEnter\n"
  },
  {
    "path": "examples/cli-ui/Gemfile",
    "content": "source \"https://rubygems.org\"\ngem 'cli-ui'\n"
  },
  {
    "path": "examples/cli-ui/README.md",
    "content": "# CLI UI\n\n### Format\n\n<img width=\"600\" src=\"./format.gif\" />\n\n```\nOutput examples/cli-ui/format.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType 'puts CLI::UI.fmt \"{{red:Red}} {{green:Green}}\"'\nSleep .5\nEnter\nSleep 5\n```\n\n### Nested Frames\n\n<img width=\"600\" src=\"./nested-frames.gif\" />\n\n```\nOutput examples/cli-ui/nested-frames.gif\n\nSet FontSize 32\n\nSet Width 2000\nSet Height 750\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI::Frame.open('Frame 1') do\"\nEnter\nType \"  CLI::UI::Frame.open('Frame 2') { puts 'inside frame 2' }\"\nEnter\nType \"  puts 'inside frame 1'\"\nEnter\nType \"end\"\n\nSleep 1\n\nEnter\n\nSleep 3\n```\n\n### Progress\n<img width=\"600\" src=\"./progress.gif\" />\n\n```\nOutput examples/cli-ui/progress.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI::Progress.progress { |bar| 100.times { sleep 0.02; bar.tick } }\"\nSleep .5\nEnter\nSleep 5\n```\n\n### Spinner\n<img width=\"600\" src=\"./spinner.gif\" />\n\n```\nOutput examples/cli-ui/spinner.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI::Spinner.spin('Spinning...') { sleep 3 }\"\nSleep .5\nEnter\nSleep 5\n```\n\n### Status Widget\n<img width=\"600\" src=\"./status-widget.gif\" />\n\n```\nOutput examples/cli-ui/status-widget.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType 'CLI::UI::Spinner.spin(\"Building: {{@widget/status:1:2:3:4}}\") { |spinner| sleep 3 }'\nSleep .5\nEnter\nSleep 5\n```\n\n### Symbols\n<img width=\"600\" src=\"./symbols.gif\" />\n\n```\nOutput examples/cli-ui/symbols.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType 'puts CLI::UI.fmt \"{{*}} {{v}} {{?}} {{x}}\"'\nSleep .5\nEnter\nSleep 5\n```\n\n### Text Prompt\n<img width=\"600\" src=\"./text-prompt.gif\" />\n\n```\nOutput examples/cli-ui/text-prompt.ascii\nOutput examples/cli-ui/text-prompt.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 500\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\"\nSleep .5\nEnter\nSleep 1\nType \"I love it!\"\nSleep 1\nEnter\nSleep 3\n```\n"
  },
  {
    "path": "examples/cli-ui/format.tape",
    "content": "Output examples/cli-ui/format.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType 'puts CLI::UI.fmt \"{{red:Red}} {{green:Green}}\"'\nSleep .5\nEnter\nSleep 5\n"
  },
  {
    "path": "examples/cli-ui/interactive-prompt.tape",
    "content": "Output examples/cli-ui/interactive-prompt.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 500\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI.ask('What do you use?', options: %w(rails go ruby python))\"\nSleep .5\nEnter\nSleep 1\n\nDown@.5 3\nSleep 1\nUp@.5 2\nSleep 1\n\nEnter\n\nSleep 3\n"
  },
  {
    "path": "examples/cli-ui/nested-frames.tape",
    "content": "Output examples/cli-ui/nested-frames.gif\n\nSet FontSize 32\n\nSet Width 2000\nSet Height 750\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI::Frame.open('Frame 1') do\"\nEnter\nType \"  CLI::UI::Frame.open('Frame 2') { puts 'inside frame 2' }\"\nEnter\nType \"  puts 'inside frame 1'\"\nEnter\nType \"end\"\n\nSleep 1\n\nEnter\n\nSleep 3\n"
  },
  {
    "path": "examples/cli-ui/progress.tape",
    "content": "Output examples/cli-ui/progress.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI::Progress.progress { |bar| 100.times { sleep 0.02; bar.tick } }\"\nSleep .5\nEnter\nSleep 5\n"
  },
  {
    "path": "examples/cli-ui/spinner.tape",
    "content": "Output examples/cli-ui/spinner.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI::Spinner.spin('Spinning...') { sleep 3 }\"\nSleep .5\nEnter\nSleep 5\n"
  },
  {
    "path": "examples/cli-ui/status-widget.tape",
    "content": "Output examples/cli-ui/status-widget.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType 'CLI::UI::Spinner.spin(\"Building: {{@widget/status:1:2:3:4}}\") { |spinner| sleep 3 }'\nSleep .5\nEnter\nSleep 5\n"
  },
  {
    "path": "examples/cli-ui/symbols.tape",
    "content": "Output examples/cli-ui/symbols.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 400\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType 'puts CLI::UI.fmt \"{{*}} {{v}} {{?}} {{x}}\"'\nSleep .5\nEnter\nSleep 5\n"
  },
  {
    "path": "examples/cli-ui/text-prompt.ascii",
    "content": "irb(main):003:0>\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n? Is CLI UI Awesome? (empty = It is great!)\n>\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n? Is CLI UI Awesome? (empty = It is great!)\n> I love it!\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n? Is CLI UI Awesome? (empty = It is great!)\n> I love it!\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n? Is CLI UI Awesome? (empty = It is great!)\n> I love it!\n=> \"I love it!\"\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\nirb(main):003:0> CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\n? Is CLI UI Awesome? (empty = It is great!)\n> I love it!\n=> \"I love it!\"\nirb(main):004:0>\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n"
  },
  {
    "path": "examples/cli-ui/text-prompt.tape",
    "content": "Output examples/cli-ui/text-prompt.ascii\nOutput examples/cli-ui/text-prompt.gif\n\nSet FontSize 32\n\nSet Width 2200\nSet Height 500\n\nHide\nType \"irb --noautocomplete\"\nEnter\nType \"require 'cli/ui'\"\nEnter\nType \"CLI::UI::StdoutRouter.enable\"\nEnter\nCtrl+L\nShow\n\nType \"CLI::UI.ask('Is CLI UI Awesome?', default: 'It is great!')\"\nSleep .5\nEnter\nSleep 1\nType \"I love it!\"\nSleep 1\nEnter\nSleep 3\n"
  },
  {
    "path": "examples/commands/README.md",
    "content": "# Commands\n\n### Arrow\n\n<img width=\"600\" src=\"./arrow.gif\" />\n\n```\nOutput examples/commands/arrow.gif\nSet FontSize 42\nSet Height 225\n\nType \"Navigate around\"\nSleep .25\nLeft 10\nSleep 1\nRight@50ms 10\nSleep 1\n```\n\n### Backspace\n\n<img width=\"600\" src=\"./backspace.gif\" />\n\n```\nOutput examples/commands/backspace.gif\nSet FontSize 42\nSet Height 225\n\nType@50ms \"Delete anything...\"\nBackspace 18\nSleep 1\n```\n\n### Comment\n\n<img width=\"600\" src=\"./comment.gif\" />\n\n```\nOutput examples/commands/comment.gif\nSet Height 500\nSet Width 1000\n\n# This is a comment.\n# These are ignored by the parser so you can write whatever you want!\n\n# Quickly comment out a command you don't need.\n# Type \"Hello, world!\"\n\nSleep 1\n```\n\n### Ctrl\n\n<img width=\"600\" src=\"./ctrl.gif\" />\n\n```\nOutput examples/commands/ctrl.gif\nSet FontSize 42\nSet Height 225\n\nSleep 1\nCtrl+R\nSleep 1\n```\n\n### Enter\n\n<img width=\"600\" src=\"./enter.gif\" />\n\n```\nOutput examples/commands/enter.gif\nSet FontSize 42\nSet Height 350\n\nSleep 1\nEnter@.5 2\nSleep 1\n```\n\n### Hide\n\n<img width=\"600\" src=\"./hide.gif\" />\n\n```\nOutput examples/commands/hide.gif\n\nSet FontSize 42\nSet Height 300\n\nHide\nType \"You won't see this being typed.\" Ctrl+C\nShow\nType \"You will see this being typed.\"\n\nSleep 2\n```\n\n### Show\n\n<img width=\"600\" src=\"./show.gif\" />\n\n```\nOutput examples/commands/show.gif\n\nHide\nType \"export HIDDEN=wow\"\nEnter\nCtrl+L\nShow\n\nType \"echo $HIDDEN\"\nEnter\nSleep 1\n```\n\n### Space\n\n<img width=\"600\" src=\"./space.gif\" />\n\n```\nOutput examples/commands/space.gif\nSet FontSize 42\nSet Height 225\n\nSleep .25\nSpace 10\nSleep 1\n```\n\n### Tab\n\n<img width=\"600\" src=\"./tab.gif\" />\n\n```\nOutput examples/commands/tab.gif\nSet FontSize 42\nSet Height 300\n\nType \"cd .\"\nSleep 0.5s\nTab@0.5s 2\nSleep 1s\n```\n\n### Type\n\n<img width=\"600\" src=\"./type.gif\" />\n\n```\nOutput examples/commands/type.gif\nSet FontSize 42\nSet Height 225\n\nSleep 1\n\n# Type something\nType \"Whatever you want\"\n\nSleep 1 Ctrl+U  Sleep 1\n\n# Type something really slowly!\nType@500ms \"Slow down there, partner.\"\n\nSleep 1\n```\n\n"
  },
  {
    "path": "examples/commands/alt.tape",
    "content": "Output examples/commands/alt.gif\nSet FontSize 42\nSet Height 225\n\nSleep 1\n\nAlt+.\n\nSleep 1\n"
  },
  {
    "path": "examples/commands/arrow.tape",
    "content": "Output examples/commands/arrow.gif\nSet FontSize 42\nSet Height 225\n\nType \"Navigate around\"\nSleep .25\nLeft 10\nSleep 1\nRight@50ms 10\nSleep 1\n"
  },
  {
    "path": "examples/commands/backspace.tape",
    "content": "Output examples/commands/backspace.gif\nSet FontSize 42\nSet Height 225\n\nType@50ms \"Delete anything...\"\nBackspace 18\nSleep 1\n"
  },
  {
    "path": "examples/commands/clipboard.tape",
    "content": "Output examples/commands/clipboard.gif\n\nSet FontSize 42\nSet Height 225\n\nCopy \"https://github.com/charmbracelet\"\nType \"open \"\nSleep 500ms\nPaste\nSleep 3s\n"
  },
  {
    "path": "examples/commands/comment.tape",
    "content": "Output examples/commands/comment.gif\nSet Height 500\nSet Width 1000\n\n# This is a comment.\n# These are ignored by the parser so you can write whatever you want!\n\n# Quickly comment out a command you don't need.\n# Type \"Hello, world!\"\n\nSleep 1\n"
  },
  {
    "path": "examples/commands/ctrl.tape",
    "content": "Output examples/commands/ctrl.gif\nSet FontSize 42\nSet Height 225\n\nSleep 1\n\nCtrl+R\n\nSleep 1\n"
  },
  {
    "path": "examples/commands/enter.tape",
    "content": "Output examples/commands/enter.gif\nSet FontSize 42\nSet Height 350\n\nSleep 1\nEnter@.5 2\nSleep 1\n"
  },
  {
    "path": "examples/commands/hide.tape",
    "content": "Output examples/commands/hide.gif\n\nSet FontSize 42\nSet Height 300\n\nHide\nType \"You won't see this being typed.\" Ctrl+C\nShow\nType \"You will see this being typed.\"\n\nSleep 2\n"
  },
  {
    "path": "examples/commands/show.tape",
    "content": "Output examples/commands/show.gif\n\nHide\nType \"export HIDDEN=wow\"\nEnter\nCtrl+L\nShow\n\nType \"echo $HIDDEN\"\nEnter\nSleep 1\n"
  },
  {
    "path": "examples/commands/space.tape",
    "content": "Output examples/commands/space.gif\nSet FontSize 42\nSet Height 225\n\nSleep .25\nSpace 10\nSleep 1\n"
  },
  {
    "path": "examples/commands/tab.tape",
    "content": "Output examples/commands/tab.gif\nSet FontSize 42\nSet Height 300\n\nType \"cd .\"\nSleep 0.5s\nTab@0.5s 2\nShift+Tab\nSleep 1s\n"
  },
  {
    "path": "examples/commands/type.tape",
    "content": "Output examples/commands/type.gif\nSet FontSize 42\nSet Height 225\n\nSleep 1\n\n# Type something\nType \"Whatever you want\"\n\nSleep 1 Ctrl+U  Sleep 1\n\n# Type something really slowly!\nType@500ms \"Slow down there, partner.\"\n\nSleep 1\n"
  },
  {
    "path": "examples/decorations/decorations.tape",
    "content": "Output examples/decorations/decorations.gif\n\nSet FontSize 28\nSet Width 1200\nSet Height 800\nSet Padding 30\n\nSet Margin 80\nSet MarginFill \"#674EFF\"\nSet WindowBar Colorful\nSet WindowBarSize 40\nSet BorderRadius 8\n\nType \"I can't believe it's not butter.\"\nSleep 2s"
  },
  {
    "path": "examples/demo.tape",
    "content": "# VHS documentation\n#\n# Output:\n#   Output <path>.gif               Create a GIF output at the given <path>\n#   Output <path>.mp4               Create an MP4 output at the given <path>\n#   Output <path>.webm              Create a WebM output at the given <path>\n#\n# Require:\n#   Require <string>                Ensure a program is on the $PATH to proceed\n#\n# Settings:\n#   Set FontSize <number>           Set the font size of the terminal\n#   Set FontFamily <string>         Set the font family of the terminal\n#   Set Height <number>             Set the height of the terminal\n#   Set Width <number>              Set the width of the terminal\n#   Set LetterSpacing <float>       Set the font letter spacing (tracking)\n#   Set LineHeight <float>          Set the font line height\n#   Set LoopOffset <float>%         Set the starting frame offset for the GIF loop\n#   Set Theme <json|string>         Set the theme of the terminal\n#   Set Padding <number>            Set the padding of the terminal\n#   Set Framerate <number>          Set the framerate of the recording\n#   Set PlaybackSpeed <float>       Set the playback speed of the recording\n#   Set MarginFill <file|#000000>   Set the file or color the margin will be filled with.\n#   Set Margin <number>             Set the size of the margin. Has no effect if MarginFill isn't set.\n#   Set BorderRadius <number>       Set terminal border radius, in pixels.\n#   Set WindowBar <string>          Set window bar type. (one of: Rings, RingsRight, Colorful, ColorfulRight)\n#   Set WindowBarSize <number>      Set window bar size, in pixels. Default is 40.\n#   Set TypingSpeed <time>          Set the typing speed of the terminal. Default is 50ms.\n#\n# Sleep:\n#   Sleep <time>                    Sleep for a set amount of <time> in seconds\n#\n# Type:\n#   Type[@<time>] \"<characters>\"    Type <characters> into the terminal with a\n#                                   <time> delay between each character\n#\n# Keys:\n#   Escape[@<time>] [number]        Press the Escape key\n#   Backspace[@<time>] [number]     Press the Backspace key\n#   Delete[@<time>] [number]        Press the Delete key\n#   Insert[@<time>] [number]        Press the Insert key\n#   Down[@<time>] [number]          Press the Down key\n#   Enter[@<time>] [number]         Press the Enter key\n#   Space[@<time>] [number]         Press the Space key\n#   Tab[@<time>] [number]           Press the Tab key\n#   Left[@<time>] [number]          Press the Left Arrow key\n#   Right[@<time>] [number]         Press the Right Arrow key\n#   Up[@<time>] [number]            Press the Up Arrow key\n#   Down[@<time>] [number]          Press the Down Arrow key\n#   PageUp[@<time>] [number]        Press the Page Up key\n#   PageDown[@<time>] [number]      Press the Page Down key\n#   Ctrl+<key>                      Press the Control key + <key> (e.g. Ctrl+C)\n#\n# Display:\n#   Hide                            Hide the subsequent commands from the output\n#   Show                            Show the subsequent commands in the output\n#   ScrollUp[@<time>] [number]      Scroll terminal viewport up by rows\n#   ScrollDown[@<time>] [number]    Scroll terminal viewport down by rows\n\nOutput examples/demo.gif\n\nRequire echo\n\nSet Shell \"bash\"\nSet FontSize 32\nSet Width 1200\nSet Height 600\n\nType \"echo 'Welcome to VHS!'\" Sleep 500ms  Enter\n\nSleep 5s\n"
  },
  {
    "path": "examples/demo.webm",
    "content": "version https://git-lfs.github.com/spec/v1\noid sha256:0444491291389ed9cdbcdda3f777c6d572d7323bd75d29ed9129c9b6e0f4d7d7\nsize 13086\n"
  },
  {
    "path": "examples/env/env.tape",
    "content": "Output examples/env/env.gif\n\nSet Width 500\nSet Height 250\n\nEnv HELLO \"WORLD\"\n\nType \"echo $HELLO\"\nSleep 500ms\nEnter\nSleep 1s\n"
  },
  {
    "path": "examples/errors/dimensions.tape",
    "content": "Set Height 100\nSet Width 100\nSet Padding 100\n\nOutput demo.gif\n\nType \"This will fail because the padding is too large for the width and height\"\n"
  },
  {
    "path": "examples/errors/parser.tape",
    "content": "Set Foo Bar\n\nFoo\n\nType Enter\n\nBar Backspace@\n\nfoo\n"
  },
  {
    "path": "examples/errors/require.tape",
    "content": "Output out.gif\n\nRequire foo\nRequire bar\n\nType \"foo\" Enter\n"
  },
  {
    "path": "examples/fixtures/all.tape",
    "content": "# All Commands\n\n# Output:\nOutput examples/fixtures/all.gif\nOutput examples/fixtures/all.mp4\nOutput examples/fixtures/all.webm\n\n# Settings:\nSet Shell \"fish\"\nSet FontSize 22\nSet FontFamily \"DejaVu Sans Mono\"\nSet Height 600\nSet Width 1200\nSet LetterSpacing 1\nSet LineHeight 1.2\nSet Theme { \"name\": \"Whimsy\", \"black\": \"#535178\", \"red\": \"#ef6487\", \"green\": \"#5eca89\", \"yellow\": \"#fdd877\", \"blue\": \"#65aef7\", \"purple\": \"#aa7ff0\", \"cyan\": \"#43c1be\", \"white\": \"#ffffff\", \"brightBlack\": \"#535178\", \"brightRed\": \"#ef6487\", \"brightGreen\": \"#5eca89\", \"brightYellow\": \"#fdd877\", \"brightBlue\": \"#65aef7\", \"brightPurple\": \"#aa7ff0\", \"brightCyan\": \"#43c1be\", \"brightWhite\": \"#ffffff\", \"background\": \"#29283b\", \"foreground\": \"#b3b0d6\", \"selectionBackground\": \"#3d3c58\", \"cursorColor\": \"#b3b0d6\" }\nSet Theme \"Catppuccin Mocha\"\nSet Padding 50\nSet Framerate 60\nSet PlaybackSpeed 2\nSet TypingSpeed .1\nSet LoopOffset 60.4\nSet LoopOffset 20.99%\nSet CursorBlink false\n\n# Sleep:\nSleep 1\nSleep 500ms\nSleep .5\nSleep 0.5\n\n# Type:\nType@.5 \"All\"\nType@500ms \"All\"\nType \"Double Quote\"\nType '\"Single\" Quote'\nType `\"Backtick\" 'Quote'`\n\n# Keys:\nBackspace\nBackspace 2\nBackspace@1 3\n\nDelete\nDelete 2\nDelete@1 3\n\nInsert\nInsert 2\nInsert@1 3\n\nDown\nDown 2\nDown@1 3\n\nPageDown\nPageDown 2\nPageDown@1 3\n\nScrollDown\nScrollDown 2\nScrollDown@1 3\n\nEnter\nEnter 2\nEnter@1 3\n\nSpace\nSpace 2\nSpace@1 3\n\nTab\nTab 2\nTab@1 3\n\nLeft\nLeft 2\nLeft@1 3\n\nRight\nRight 2\nRight@1 3\n\nUp\nUp 2\nUp@1 3\n\nPageUp\nPageUp 2\nPageUp@1 3\n\nScrollUp\nScrollUp 2\nScrollUp@1 3\n\nDown\nDown 2\nDown@1 3\n\n# Control:\nCtrl+C\nCtrl+L\nCtrl+R\n\n# Alt:\nAlt+.\nAlt+L\nAlt+i\n\n# Display:\nHide\nShow\n"
  },
  {
    "path": "examples/gh-cli/README.md",
    "content": "# GitHub CLI\n\n### GitHub PR List\n\n<img width=\"600\" src=\"./gh-pr.gif\" />\n\n```\nOutput examples/gh-cli/gh-pr.gif\n\nType \"gh pr list --state all\"\nSleep 500ms\nEnter\n\nSleep 5s\n```\n\n### GitHub Issue List\n\n<img width=\"600\" src=\"./gh-issue.gif\" />\n\n```\nOutput examples/gh-cli/gh-issue.gif\n\nType \"gh issue list\"\nSleep 500ms\nEnter 1\nSleep 4s\n\nCtrl+L\nSleep 500ms\n\nType \"gh issue view 19\"\nSleep 500ms\nEnter\n\nSleep 5s\n```\n"
  },
  {
    "path": "examples/gh-cli/gh-issue.tape",
    "content": "Output examples/gh-cli/gh-issue.gif\n\nType \"gh issue list\"\nSleep 500ms\nEnter 1\nSleep 4s\n\nCtrl+L\nSleep 500ms\n\nType \"gh issue view 19\"\nSleep 500ms\nEnter\n\nSleep 5s\n"
  },
  {
    "path": "examples/gh-cli/gh-pr.tape",
    "content": "Output examples/gh-cli/gh-pr.gif\n\nType \"gh pr list --state all\"\nSleep 500ms\nEnter\n\nSleep 5s\n"
  },
  {
    "path": "examples/glow/CarrotCake.md",
    "content": "# Carrot Cake\n\nCarrot cake is delicious. And, it takes only 20 minutes to make!\n\nHere is the recipe:\n\n * Carrots\n * Cake\n\n Tada!\n"
  },
  {
    "path": "examples/glow/NiHao.md",
    "content": "# 你好\n"
  },
  {
    "path": "examples/glow/README.md",
    "content": "# Glow\n\n### Glow Simple\n\n<img width=\"600\" src=\"./glow-simple.gif\" />\n\n```\nOutput examples/glow/glow-simple.ascii\nOutput examples/glow/glow-simple.gif\n\nSet Width 1000\nSet Height 1050\n\nType \"glow\"\nEnter\nSleep 1s\nEnter\nSleep 1s\nEscape\nSleep 1s\nType \"q\"\nSleep 1s\n```\n\n### Glow Full\n\n<img width=\"600\" src=\"./vhs-glow.gif\" />\n\n```\nOutput examples/glow/vhs-glow.gif\nOutput examples/glow/glow.ascii\n\nSet Width 1600\nSet Height 1040\n\nSleep 1s\n\nType \"glow\"\n\nSleep 100ms\n\nEnter\n\nSleep 1s\n\nHide\nTab\nType \"/artichoke\"\nEnter\nDown 2\nShow\n\nSleep 0.5s\n\nDown 20\n\nHide\nEscape\nType \"l\"\nDown 5\nShow\n\nSleep 1s\nUp@400ms 5\n\nHide\nType \"/ulysses\"\nEnter\nShow\n\nSleep 0.5s\n\nDown@200ms 20\n\nHide\nEscape\nType \"/\"\nShow\n\nSleep 0.5s\n\nType@500ms \"todo\"\nSleep 1\n\nHide\nEscape\nType \"/ulysses\"\nEnter\nShow\n\nSleep 0.5s\n\nType@750ms \"????\"\n\nHide\nEscape\nType \"/artichoke\"\nEnter\nType \"m\"\nCtrl+A\nRight 4\nShow\n\nSleep 1s\nType@250ms \"Tasty \"\nSleep 1s\n\nHide\nEscape\nDown 5\nType \"m\"\nCtrl+U\nShow\n\nSleep 1s\nType@150ms \"Your new internet thing\"\nSleep 3s\n\nHide\nCtrl+C\nShow  \n```\n"
  },
  {
    "path": "examples/glow/StewedPeaches.md",
    "content": "# Stewed Peaches\n"
  },
  {
    "path": "examples/glow/glow-edit.tape",
    "content": "Output glow-edit.gif\nSet FontSize 22\n\nSleep .5s\nType \"glow\"\nEnter\nSleep 1.5s\nEnter\nSleep 1s\nType \"e\"\nSleep 1s\nType@100ms \"jjjjjjjo\"\nSleep 0.5s\nType \" * Love\"\nSleep 1s\nEscape\nSleep 1s\nType@300ms \":wq\"\nSleep 1s\nEnter\nSleep 2s\nType \"c\"\nSleep 4s\n\n\n"
  },
  {
    "path": "examples/glow/glow-simple.ascii",
    "content": "> glow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n> glow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n\n    Glow\n\n   9 local │ 14 stashed │ 3 news\n\n │ CarrotCake.md\n │ 2 days ago\n\n   StewedPeaches.md\n   2 days ago\n\n   notes/Currywurst.md\n   2 days ago\n\n   notes/Käsewurst.md\n   2 days ago\n\n   notes/Spätzle.md\n   2 days ago\n\n   notes/Weißwurst.md\n   2 days ago\n\n   to-do/Okonomiyaki.md\n   2 days ago\n\n   ••\n\n   tab section • h/l ←/→ page • / find • s stash • …\n\n────────────────────────────────────────────────────────────────────────────────\n\n   Carrot Cake\n\n  Carrot cake is delicious. And, it takes only 20 minutes to\n  make!\n\n  Here is the recipe:\n\n  • Carrots\n  • Cake\n\n  Tada!\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n\n   Carrot Cake\n\n  Carrot cake is delicious. And, it takes only 20 minutes to\n  make!\n\n  Here is the recipe:\n\n  • Carrots\n  • Cake\n\n  Tada!\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n Glow  CarrotCake.md                              100%  ? Help\n────────────────────────────────────────────────────────────────────────────────\n\n   Carrot Cake\n\n  Carrot cake is delicious. And, it takes only 20 minutes to\n  make!\n\n  Here is the recipe:\n\n  • Carrots\n  • Cake\n\n  Tada!\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n Glow  CarrotCake.md                              100%  ? Help\n────────────────────────────────────────────────────────────────────────────────\n\n    Glow\n\n   9 local │ 14 stashed │ 3 news\n\n │ CarrotCake.md\n │ 2 days ago\n\n   StewedPeaches.md\n   2 days ago\n\n   notes/Currywurst.md\n   2 days ago\n\n   notes/Käsewurst.md\n   2 days ago\n\n   notes/Spätzle.md\n   2 days ago\n\n   notes/Weißwurst.md\n   2 days ago\n\n   to-do/Okonomiyaki.md\n   2 days ago\n\n   ••\n\n   tab section • h/l ←/→ page • / find • s stash • …\n\n────────────────────────────────────────────────────────────────────────────────\n> glow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n> glow\n\n  Thanks for using Glow!\n\n>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n"
  },
  {
    "path": "examples/glow/glow-simple.tape",
    "content": "Output examples/glow/glow-simple.ascii\nOutput examples/glow/glow-simple.gif\n\nSet Width 1000\nSet Height 1050\n\nType \"glow\"\nEnter\nSleep 1s\nEnter\nSleep 1s\nEscape\nSleep 1s\nType \"q\"\nSleep 1s\n"
  },
  {
    "path": "examples/glow/glow.ascii",
    "content": ">\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n> glow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n> glow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n> glow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n\n    Glow\n\n   9 local │ 14 stashed │ 3 news\n\n │ CarrotCake.md\n │ 2 days ago\n\n   StewedPeaches.md\n   2 days ago\n\n   notes/Currywurst.md\n   2 days ago\n\n   notes/Käsewurst.md\n   2 days ago\n\n   notes/Spätzle.md\n   2 days ago\n\n   notes/Weißwurst.md\n   2 days ago\n\n   to-do/Okonomiyaki.md\n   2 days ago\n\n   ••\n\n   tab section • h/l ←/→ page • / find • s stash • q quit • ? more\n\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n  1. Carrots\n  2. Celery\n  3. Tacos\n    • Soft\n    • Hard\n  4. Cucumber\n\n  ## Things to eat today\n\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n  1. Carrots\n  2. Celery\n  3. Tacos\n    • Soft\n    • Hard\n  4. Cucumber\n\n  ## Things to eat today\n\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n  1. Carrots\n  2. Celery\n  3. Tacos\n    • Soft\n    • Hard\n  4. Cucumber\n\n  ## Things to eat today\n\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n    Glow\n\n   9 local │ 14 stashed │ 3 news\n\n   • 牛油果 🥑\n   04 Sep 2022 17:04 UTC\n\n   • Hello from Glow\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n    Glow\n\n   9 local │ 14 stashed │ 3 news\n\n   • 牛油果 🥑\n   04 Sep 2022 17:04 UTC\n\n   • Hello from Glow\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n    Glow\n\n   9 local │ 14 stashed │ 3 news\n\n │ • 牛油果 🥑\n │ 04 Sep 2022 17:04 UTC\n\n   • Hello from Glow\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n   Find: ulysses\n\n   1 stashed\n\n │ • Ulysses by James Joyce\n │ 04 Sep 2022 17:11 UTC\n\n\n────────────────────────────────────────────────────────────────────────────────\n\n   Glamour\n\n  A casual introduction. 你好世界!\n\n  ## Let’s talk about artichokes\n\n  The artichoke is mentioned as a garden plant in the 8th century BC by Homer and Hesiod. The naturally\n  occurring variant of the artichoke, the cardoon, which is native to the Mediterranean area, also has\n  records of use as a food among the ancient Greeks and Romans. Pliny the Elder mentioned growing of carduus\n  in Carthage and Cordoba.\n\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n  and hued like pale oak.\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n  │ He holds him with a skinny hand,\n  │ ‘There was a ship,’ quoth he.\n  │ ‘Hold off! unhand me, grey-beard loon!’\n  │ An artichoke, dropt he.\n\n  --Samuel Taylor Coleridge, The Rime of the Ancient Mariner https://poetryfoundation.org/poems/43997/\n\n  ## Other foods worth mentioning\n\n\n  Ulysses\n\n  by James Joyce\n\n  Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of lather on which a mirror and a\n  razor lay crossed. A yellow dressinggown, ungirdled, was sustained gently behind him on the mild morning\n  air. He held the bowl aloft and intoned:\n\n  —Introibo ad altare Dei.\n\n  Halted, he peered down the dark winding stairs and called out coarsely:\n\n  \"Come up, Kinch! Come up, you fearful jesuit!\"\n\n  Solemnly he came forward and mounted the round gunrest. He faced about and blessed gravely thrice the\n  tower, the surrounding land and the awaking mountains. Then, catching sight of Stephen Dedalus, he bent\n  towards him and made rapid crosses in the air, gurgling in his throat and shaking his head. Stephen\n  Dedalus, displeased and sleepy, leaned his arms on the top of the staircase and looked coldly at the\n  shaking gurgling face that blessed him, equine in its length, and at the light untonsured hair, grained\n\n────────────────────────────────────────────────────────────────────────────────\n> glow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n────────────────────────────────────────────────────────────────────────────────\n"
  },
  {
    "path": "examples/glow/glow.tape",
    "content": "Output vhs-glow.gif\nOutput glow.ascii\n\nSet Framerate 40\nSet Width 1600\nSet Height 1040\n\nSleep 1s\n\nType \"glow\"\nSleep 100ms\nEnter\n\nSleep 1s\n\nHide\nSleep 5s\nShow\n\nHide\nType \"/artichoke\"\nEnter\nSleep 2s\nDown 2\nShow\n\nSleep 0.5s\n\nDown 20\n\nHide\nEscape\nType \"l\"\nDown 5\nShow\n\nSleep 1s\nUp@400ms 5\n\nHide\nType \"/ulysses\"\nEnter\nSleep 2s\nShow\n\nSleep 0.5s\n\nDown@200ms 20\n\nHide\nEscape\nType \"/\"\nShow\n\nSleep 0.5s\n\nType@500ms \"Readme\"\nSleep 1\nEnter\nSleep 1\nType \"s\"\nSleep 1\nEnter\nSleep 2\n\nHide\nEscape\nType \"/ulysses\"\nEnter\nSleep 2s\nShow\n\nSleep 0.5s\n\nType@750ms \"????\"\n\nHide\nSleep 1s\nEscape\nSleep 1s\nType \"/artichoke\"\nEnter\nSleep 2s\nType \"m\"\nCtrl+A\nRight 4\nShow\n\nSleep 1s\nType@250ms \"Tasty \"\nSleep 1s\n\nHide\nEscape\nType \"a\"\nSleep 1\nShow\n\nType \"j\"\nSleep 1\nType \"k\"\nSleep 1\nEnter\nSleep 2\nEscape\n\nSleep 1\nTab\nSleep 1\nType@200ms \"jjjjjj\"\nSleep 1\nEnter\nSleep 2\n\nHide\nEscape\nEscape\nType \"G\"\nType \"m\"\nCtrl+U\nShow\n\nSleep 1s\nType@150ms \"Your new internet thing\"\nSleep 3s\n\nHide\nCtrl+C\nShow\n"
  },
  {
    "path": "examples/glow/notes/Currywurst.md",
    "content": "# Currywurst\n"
  },
  {
    "path": "examples/glow/notes/Kasewurst.md",
    "content": "# Käsewurst\n"
  },
  {
    "path": "examples/glow/notes/Spatzle.md",
    "content": "# Spätzle\n"
  },
  {
    "path": "examples/glow/notes/Weibwurst.md",
    "content": "# Weißwurst\n"
  },
  {
    "path": "examples/glow/to-do/Okonomiyaki.md",
    "content": "# Okonomiyaki\n"
  },
  {
    "path": "examples/glow/to-do/Takoyaki.md",
    "content": "# Takoyaki\n"
  },
  {
    "path": "examples/gum/README.md",
    "content": "# Gum\n\n### File\n\n<img width=\"600\" src=\"file.gif\" />\n\n```\nOutput examples/gum/file.gif\n\nType \"gum file ./src\"\nSleep 0.5s\nEnter\nSleep 0.5s\nDown@250ms 4\nUp@250ms 1\nSleep 0.5s\nEnter\nSleep 0.5s\nDown@250ms 4\nSleep 0.5s\nUp@250ms 2\nSleep 1s\n```\n\n### Pager\n\n<img width=\"600\" src=\"pager.gif\" />\n\n```\nOutput examples/gum/pager.gif\n\nSet Padding 32\nSet FontSize 16\nSet Height 600\n\nType \"gum pager < ~/src/gum/README.md --border normal\"\nSleep 0.5s\nEnter\nSleep 1s\nDown@15ms 40\nSleep 0.5s\nUp@15ms 30\nSleep 0.5s\nDown@15ms 20\nSleep 2s\n```\n\n### Table\n\n<img width=\"600\" src=\"pager.gif\" />\n\n```\nOutput examples/gum/table.gif\n\nType \"gum table < superhero.csv -w 2,12,5,6,6,8,4,20 --height 10\"\nEnter\nSleep 0.5s\nDown 10\nSleep 0.5s\nDown 10\nSleep 0.5s\nUp 10\nSleep 0.5s\nEnter\nSleep 2s\n```\n"
  },
  {
    "path": "examples/gum/file.tape",
    "content": "Output examples/gum/file.gif\n\nType \"gum file ./src\"\nSleep 0.5s\nEnter\nSleep 0.5s\nDown@250ms 4\nUp@250ms 1\nSleep 0.5s\nEnter\nSleep 0.5s\nDown@250ms 4\nSleep 0.5s\nUp@250ms 2\nSleep 1s\n"
  },
  {
    "path": "examples/gum/pager.tape",
    "content": "Output examples/gum/pager.gif\n\nSet Padding 32\nSet FontSize 16\nSet Height 600\n\nType \"gum pager < ~/src/gum/README.md --border normal\"\nSleep 0.5s\nEnter\nSleep 1s\nDown@15ms 40\nSleep 0.5s\nUp@15ms 30\nSleep 0.5s\nDown@15ms 20\nSleep 2s\n"
  },
  {
    "path": "examples/gum/src/id_rsa",
    "content": "-----BEGIN OPENSSH PRIVATE KEY-----\nLorem ipsum dolor sit amet, officia\nexcepteur ex fugiat reprehenderit enim\nlabore culpa sint ad nisi Lorem pariatur\nmollit ex esse exercitation amet. Nisi anim\ncupidatat excepteur officia. Reprehenderit\nnostrud nostrud ipsum Lorem est aliquip\namet voluptate voluptate dolor minim nulla\nest proident. Nostrud officia pariatur ut\nofficia. Sit irure elit esse ea nulla sunt\nex occaecat reprehenderit commodo officia\ndolor Lorem duis laboris cupidatat officia\nvoluptate. Culpa proident adipisicing id\nnulla nisi laboris ex in Lorem sunt duis\nofficia eiusmod. Aliqua reprehenderit\ncommodo ex non excepteur duis sunt velit\nenim. Voluptate laboris sint cupidatat\nullamco ut ea consectetur et est culpa et\nLorem ipsum dolor sit amet, officia\nexcepteur ex fugiat reprehenderit enim\nlabore culpa sint ad nisi Lorem pariatur\nmollit ex esse exercitation amet. Nisi anim\ncupidatat excepteur officia. Reprehenderit\nnostrud nostrud ipsum Lorem est aliquip\namet voluptate voluptate dolor minim nulla\nest proident. Nostrud officia pariatur ut\nofficia. Sit irure elit esse ea nulla sunt\nex occaecat reprehenderit commodo officia\ndolor Lorem duis laboris cupidatat officia\nvoluptate. Culpa proident adipisicing id\nnulla nisi laboris ex in Lorem sunt duis\nofficia eiusmod. Aliqua reprehenderit\ncommodo ex non excepteur duis sunt velit\nenim. Voluptate laboris sint cupidatat\nullamco ut ea consectetur et est culpa et\n-----END OPENSSH PRIVATE KEY-----\n"
  },
  {
    "path": "examples/gum/src/id_rsa.pub",
    "content": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILiaVloJZCKCsZcYnslysVnInqwgIlEgBp1LvOktoGjP maas@lalani.dev\n"
  },
  {
    "path": "examples/gum/src/lipgloss/README.md",
    "content": "Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\nLorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\nLorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\nLorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n"
  },
  {
    "path": "examples/gum/src/lipgloss/align.go",
    "content": "// Package lipgloss is an example package.\npackage lipgloss\n\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n"
  },
  {
    "path": "examples/gum/src/lipgloss/borders.go",
    "content": "package lipgloss\n\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n"
  },
  {
    "path": "examples/gum/src/lipgloss/colors.go",
    "content": "package lipgloss\n\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim\n// labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi\n// anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem\n// est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud\n// officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat\n// reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia\n// voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt\n// duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt\n// velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est\n// culpa et culpa duis.\n"
  },
  {
    "path": "examples/gum/src/lipgloss/join.go",
    "content": "package lipgloss\n\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim\n// labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet.\n// Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum\n// Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident.\n// Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex\n// occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat\n// officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem\n// sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis\n// sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur\n// et est culpa et culpa duis. Lorem ipsum dolor sit amet, officia excepteur ex\n// fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex\n// esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit\n// nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim\n// nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea\n// nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris\n// cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris\n// ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non\n// excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea\n// consectetur et est culpa et culpa duis.\n"
  },
  {
    "path": "examples/gum/src/lipgloss/style.go",
    "content": "package lipgloss\n\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n// Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.\n"
  },
  {
    "path": "examples/gum/src/super_secret_message.txt",
    "content": "Hello!\n"
  },
  {
    "path": "examples/gum/superhero.csv",
    "content": "ID,Name,Gender,Eye color,Race,Hair color,Height,Publisher,Skin color,Alignment,Weight\n0,A-Bomb,Male,yellow,Human,No Hair,203,Marvel Comics,-,good,441\n1,Abe Sapien,Male,blue,Icthyo Sapien,No Hair,191,Dark Horse Comics,blue,good,65\n2,Abin Sur,Male,blue,Ungaran,No Hair,185,DC Comics,red,good,90\n3,Abomination,Male,green,Human / Radiation,No Hair,203,Marvel Comics,-,bad,441\n4,Abraxas,Male,blue,Cosmic Entity,Black,-99,Marvel Comics,-,bad,-99\n5,Absorbing Man,Male,blue,Human,No Hair,193,Marvel Comics,-,bad,122\n6,Adam Monroe,Male,blue,-,Blond,-99,NBC - Heroes,-,good,-99\n7,Adam Strange,Male,blue,Human,Blond,185,DC Comics,-,good,88\n8,Agent 13,Female,blue,-,Blond,173,Marvel Comics,-,good,61\n9,Agent Bob,Male,brown,Human,Brown,178,Marvel Comics,-,good,81\n10,Agent Zero,Male,-,-,-,191,Marvel Comics,-,good,104\n11,Air-Walker,Male,blue,-,White,188,Marvel Comics,-,bad,108\n12,Ajax,Male,brown,Cyborg,Black,193,Marvel Comics,-,bad,90\n13,Alan Scott,Male,blue,-,Blond,180,DC Comics,-,good,90\n14,Alex Mercer,Male,-,Human,-,-99,Wildstorm,-,bad,-99\n15,Alex Woolsly,Male,-,-,-,-99,NBC - Heroes,-,good,-99\n16,Alfred Pennyworth,Male,blue,Human,Black,178,DC Comics,-,good,72\n17,Alien,Male,-,Xenomorph XX121,No Hair,244,Dark Horse Comics,black,bad,169\n18,Allan Quatermain,Male,-,-,-,-99,Wildstorm,-,good,-99\n19,Amazo,Male,red,Android,-,257,DC Comics,-,bad,173\n20,Ammo,Male,brown,Human,Black,188,Marvel Comics,-,bad,101\n21,Ando Masahashi,Male,-,-,-,-99,NBC - Heroes,-,good,-99\n22,Angel,Male,blue,-,Blond,183,Marvel Comics,-,good,68\n23,Angel,Male,-,Vampire,-,-99,Dark Horse Comics,-,good,-99\n24,Angel Dust,Female,yellow,Mutant,Black,165,Marvel Comics,-,good,57\n25,Angel Salvadore,Female,brown,-,Black,163,Marvel Comics,-,good,54\n26,Angela,Female,-,-,-,-99,Image Comics,-,bad,-99\n27,Animal Man,Male,blue,Human,Blond,183,DC Comics,-,good,83\n28,Annihilus,Male,green,-,No Hair,180,Marvel Comics,-,bad,90\n29,Ant-Man,Male,blue,Human,Blond,211,Marvel Comics,-,good,122\n30,Ant-Man II,Male,blue,Human,Blond,183,Marvel Comics,-,good,86\n31,Anti-Monitor,Male,yellow,God / Eternal,No Hair,61,DC Comics,-,bad,-99\n32,Anti-Spawn,Male,-,-,-,-99,Image Comics,-,bad,-99\n33,Anti-Venom,Male,blue,Symbiote,Blond,229,Marvel Comics,-,-,358\n34,Apocalypse,Male,red,Mutant,Black,213,Marvel Comics,grey,bad,135\n35,Aquababy,Male,blue,-,Blond,-99,DC Comics,-,good,-99\n36,Aqualad,Male,blue,Atlantean,Black,178,DC Comics,-,good,106\n37,Aquaman,Male,blue,Atlantean,Blond,185,DC Comics,-,good,146\n38,Arachne,Female,blue,Human,Blond,175,Marvel Comics,-,good,63\n39,Archangel,Male,blue,Mutant,Blond,183,Marvel Comics,blue,good,68\n40,Arclight,Female,violet,-,Purple,173,Marvel Comics,-,bad,57\n41,Ardina,Female,white,Alien,Orange,193,Marvel Comics,gold,good,98\n42,Ares,Male,brown,-,Brown,185,Marvel Comics,-,good,270\n43,Ariel,Female,purple,-,Pink,165,Marvel Comics,-,good,59\n44,Armor,Female,black,-,Black,163,Marvel Comics,-,good,50\n45,Arsenal,Male,-,Human,-,-99,DC Comics,-,good,-99\n46,Astro Boy,Male,brown,-,Black,-99,,-,good,-99\n47,Atlas,Male,brown,Mutant,Red,183,Marvel Comics,-,good,101\n48,Atlas,Male,blue,God / Eternal,Brown,198,DC Comics,-,bad,126\n49,Atom,Male,blue,-,Red,178,DC Comics,-,good,68\n50,Atom,Male,-,-,-,-99,DC Comics,-,good,-99\n51,Atom Girl,Female,black,-,Black,168,DC Comics,-,good,54\n52,Atom II,Male,brown,Human,Auburn,183,DC Comics,-,good,81\n53,Atom III,Male,-,-,Red,-99,DC Comics,-,good,-99\n54,Atom IV,Male,brown,-,Black,-99,DC Comics,-,good,72\n55,Aurora,Female,blue,Mutant,Black,180,Marvel Comics,-,good,63\n56,Azazel,Male,yellow,Neyaphem,Black,183,Marvel Comics,red,bad,67\n57,Azrael,Male,brown,Human,Black,-99,DC Comics,-,good,-99\n58,Aztar,Male,-,-,-,-99,DC Comics,-,good,-99\n59,Bane,Male,-,Human,-,203,DC Comics,-,bad,180\n60,Banshee,Male,green,Human,Strawberry Blond,183,Marvel Comics,-,good,77\n61,Bantam,Male,brown,-,Black,165,Marvel Comics,-,good,54\n62,Batgirl,Female,-,-,-,-99,DC Comics,-,good,-99\n63,Batgirl,Female,green,Human,Red,170,DC Comics,-,good,57\n64,Batgirl III,Female,-,-,-,-99,DC Comics,-,good,-99\n65,Batgirl IV,Female,green,Human,Black,165,DC Comics,-,good,52\n66,Batgirl V,Female,-,-,-,-99,DC Comics,-,good,-99\n67,Batgirl VI,Female,blue,-,Blond,168,DC Comics,-,good,61\n68,Batman,Male,blue,Human,black,188,DC Comics,-,good,95\n69,Batman,Male,blue,Human,Black,178,DC Comics,-,good,77\n70,Batman II,Male,blue,Human,Black,178,DC Comics,-,good,79\n71,Battlestar,Male,brown,-,Black,198,Marvel Comics,-,good,133\n72,Batwoman V,Female,green,Human,Red,178,DC Comics,-,good,-99\n73,Beak,Male,black,-,White,175,Marvel Comics,-,good,63\n74,Beast,Male,blue,Mutant,Blue,180,Marvel Comics,blue,good,181\n75,Beast Boy,Male,green,Human,Green,173,DC Comics,green,good,68\n76,Beetle,Male,-,-,-,-99,Marvel Comics,-,bad,-99\n77,Ben 10,Male,-,-,-,-99,DC Comics,-,good,-99\n78,Beta Ray Bill,Male,-,-,No Hair,201,Marvel Comics,-,good,216\n79,Beyonder,Male,-,God / Eternal,-,-99,Marvel Comics,-,good,-99\n80,Big Barda,Female,blue,New God,Black,188,DC Comics,-,bad,135\n81,Big Daddy,Male,-,-,-,-99,Icon Comics,-,good,-99\n82,Big Man,Male,blue,-,Brown,165,Marvel Comics,-,bad,71\n83,Bill Harken,Male,-,Alpha,-,-99,SyFy,-,good,-99\n84,Billy Kincaid,Male,-,-,-,-99,Image Comics,-,bad,-99\n85,Binary,Female,blue,-,Blond,180,Marvel Comics,-,good,54\n86,Bionic Woman,Female,blue,Cyborg,Black,-99,,-,good,-99\n87,Bird-Brain,-,-,-,-,-99,Marvel Comics,-,good,-99\n88,Bird-Man,Male,-,Human,-,-99,Marvel Comics,-,bad,-99\n89,Bird-Man II,Male,-,Human,-,-99,Marvel Comics,-,bad,-99\n90,Birdman,Male,-,God / Eternal,-,-99,Hanna-Barbera,-,good,-99\n91,Bishop,Male,brown,Mutant,No Hair,198,Marvel Comics,-,good,124\n92,Bizarro,Male,black,Bizarro,Black,191,DC Comics,white,neutral,155\n93,Black Abbott,Male,red,-,Black,-99,Marvel Comics,-,bad,-99\n94,Black Adam,Male,brown,-,Black,191,DC Comics,-,bad,113\n95,Black Bolt,Male,blue,Inhuman,Black,188,Marvel Comics,-,good,95\n96,Black Canary,Female,blue,Human,Blond,165,DC Comics,-,good,58\n97,Black Canary,Female,blue,Metahuman,Blond,170,DC Comics,-,good,59\n98,Black Cat,Female,green,Human,Blond,178,Marvel Comics,-,good,54\n99,Black Flash,Male,-,God / Eternal,-,-99,DC Comics,-,neutral,-99\n100,Black Goliath,Male,-,-,-,-99,Marvel Comics,-,good,-99\n101,Black Knight III,Male,brown,Human,Brown,183,Marvel Comics,-,good,86\n102,Black Lightning,Male,brown,-,No Hair,185,DC Comics,-,good,90\n103,Black Mamba,Female,green,-,Black,170,Marvel Comics,-,bad,52\n104,Black Manta,Male,black,Human,No Hair,188,DC Comics,-,bad,92\n105,Black Panther,Male,brown,Human,Black,183,Marvel Comics,-,good,90\n106,Black Widow,Female,green,Human,Auburn,170,Marvel Comics,-,good,59\n107,Black Widow II,Female,blue,-,Blond,170,Marvel Comics,-,good,61\n108,Blackout,Male,red,Demon,White,191,Marvel Comics,white,bad,104\n109,Blackwing,Male,blue,-,Black,185,Marvel Comics,-,bad,86\n110,Blackwulf,Male,red,Alien,White,188,Marvel Comics,-,-,88\n111,Blade,Male,brown,Vampire,Black,188,Marvel Comics,-,good,97\n112,Blaquesmith,-,black,-,No Hair,-99,Marvel Comics,-,good,-99\n113,Bling!,Female,-,-,-,168,Marvel Comics,-,good,68\n114,Blink,Female,green,Mutant,Magenta,165,Marvel Comics,pink,good,56\n115,Blizzard,Male,-,-,-,-99,Marvel Comics,-,bad,-9\n"
  },
  {
    "path": "examples/gum/table.tape",
    "content": "Output examples/gum/table.gif\n\nType \"gum table < superhero.csv -w 2,12,5,6,6,8,4,20 --height 10\"\nEnter\nSleep 0.5s\nDown 10\nSleep 0.5s\nDown 10\nSleep 0.5s\nUp 10\nSleep 0.5s\nEnter\nSleep 2s\n"
  },
  {
    "path": "examples/jqp/README.md",
    "content": "# JQP\n\n<img width=\"600\" src=\"./jqp.gif\" />\n\n```\nOutput examples/jqp/jqp.gif\nSet Width 2400\nSet Height 1600\n\nHide\nType \"curl https://dummyjson.com/products | jqp\"\nEnter\nSleep 1\nShow\n\nSleep 1\n\nType@.2'[ .products[] | select(.category==\"smartphones\") ]'\nSleep 1\nEnter\n\nSleep 1\nTab\n\nSleep 1\nDown@25ms 20\n\nSleep .5\nDown@25ms 20\n\nTab\n\nSleep .5\nDown@25ms 30\n\nSleep 1\nCtrl+S\n\nSleep 3\n\nEscape\n\nSleep 3\n```\n"
  },
  {
    "path": "examples/jqp/jqp.tape",
    "content": "Output examples/jqp/jqp.gif\nSet Width 2400\nSet Height 1600\n\nHide\nType \"curl https://dummyjson.com/products | jqp\"\nEnter\nSleep 1\nShow\n\nSleep 1\n\nType@.2'[ .products[] | select(.category==\"smartphones\") ]'\nSleep 1\nEnter\n\nSleep 1\nTab\n\nSleep 1\nDown@25ms 20\n\nSleep .5\nDown@25ms 20\n\nTab\n\nSleep .5\nDown@25ms 30\n\nSleep 1\nCtrl+S\n\nSleep 3\n\nEscape\n\nSleep 3\n"
  },
  {
    "path": "examples/meta.tape",
    "content": "Output examples/meta.webm\nOutput examples/meta.mp4\n\nSet Width 1920\nSet Height 1080\nSet FontSize 32\nSet Framerate 30\nSet Theme { \"brightGreen\": \"#00D787\", \"brightYellow\": \"#FE5F86\", \"yellow\": \"#FFFFFF\", \"brightBlue\": \"#875FFF\" }\n\nHide\nType \"cp examples/welcome.tape cassette.tape && clear\" Enter\nShow\n\nType \"vhs < cassette.tape\" Sleep 0.5 Enter\n\nSleep 30s\n\nHide\nType \"rm cassette.tape\" Enter\n"
  },
  {
    "path": "examples/neofetch/README.md",
    "content": "# Neofetch\n\n<img width=\"600\" src=\"neofetch.gif\" />\n\n```\n# Source code for the VHS neofetch example.\n#\n# To run:\n#\n#     vhs < neofetch.tape\n\nOutput examples/neofetch/neofetch.gif\nOutput examples/neofetch/neofetch.mp4\nOutput examples/neofetch/neofetch.webm\nOutput examples/neofetch/frames/\n\nSet TypingSpeed 75ms\nSet FontSize 22\nSet Width 1300\nSet Height 650\n\nType \"neofetch\"\n\nSleep 500ms\n\nEnter\n\nSleep 2s\n\nType \"Welcome to VHS!\"\n\nSleep 1\n\nSpace\n\nType \"A tool for generating terminal GIFs from code.\"\n\nSleep 5s\n```\n"
  },
  {
    "path": "examples/neofetch/colorize-ascii.go",
    "content": "// Package neofetch is an example package.\n//\n//nolint:unused\npackage neofetch\n\nimport (\n\t_ \"embed\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n\t\"github.com/muesli/termenv\"\n)\n\n//go:embed vhs.ascii\nvar art string\n\nfunc main() {\n\tlipgloss.SetColorProfile(termenv.TrueColor)\n\n\tvar (\n\t\tb      strings.Builder\n\t\tlines  = strings.Split(art, \"\\n\")\n\t\tcolors = []string{\"#AD92FF\", \"#9D7CFF\", \"#906BFF\", \"#8056FF\"}\n\t\tstep   = len(lines) / len(colors)\n\t)\n\n\tfor i, l := range lines {\n\t\tn := clamp(0, len(colors)-1, i/step)\n\t\tb.WriteString(colorize(colors[n], l))\n\t\tb.WriteRune('\\n')\n\t}\n\n\tfmt.Print(b.String())\n}\n\nfunc colorize(c, s string) string {\n\treturn lipgloss.NewStyle().Foreground(lipgloss.Color(c)).Render(s)\n}\n\nfunc clamp(v, low, high int) int {\n\tif high < low {\n\t\tlow, high = high, low\n\t}\n\treturn min(high, max(low, v))\n}\n"
  },
  {
    "path": "examples/neofetch/neofetch.tape",
    "content": "# Source code for the VHS neofetch example.\n#\n# To run:\n#\n#     vhs < neofetch.tape\n\nOutput examples/neofetch/neofetch.gif\nOutput examples/neofetch/neofetch.mp4\nOutput examples/neofetch/neofetch.webm\nOutput examples/neofetch/frames/\n\nSet TypingSpeed 75ms\nSet FontSize 22\nSet Width 1300\nSet Height 650\n\nType \"neofetch\"\n\nSleep 500ms\n\nEnter\n\nSleep 2s\n\nType \"Welcome to VHS!\"\n\nSleep 1\n\nSpace\n\nType \"A tool for generating terminal GIFs from code.\"\n\nSleep 5s\n"
  },
  {
    "path": "examples/neofetch/neofetch.webm",
    "content": "version https://git-lfs.github.com/spec/v1\noid sha256:c21bf41b43a78165a5f9f2ba8344ad26b89c1ef02bafff6a53ace70fcf848972\nsize 290879\n"
  },
  {
    "path": "examples/neofetch/vhs-color.ascii",
    "content": "\u001b[38;2;173;146;255m     .--.   .--.   .-.   ,.-.     ,.-s-.\u001b[0m\n\u001b[38;2;173;146;255m ,p#G*\"\"TG#Gf\"\"*GG#\"\"\"@###\"\"\"$#p#GW\"\"^\"\"%G#,\u001b[0m\n\u001b[38;2;173;146;255m{GGG      Gp     G     GG     GG^         \"G#\u001b[0m\n\u001b[38;2;157;124;255m@GGG[     G     ]G     GG     Gf     N     @G\u001b[0m\n\u001b[38;2;157;124;255m'GGGG     G     #G     GG     Gb     %b    #G\u001b[0m\n\u001b[38;2;157;124;255m GGGG     @     GG            GG       \"$GGf\u001b[0m\n\u001b[38;2;144;107;255m ]GGG#    '    lGG            GGGN,      `@#,\u001b[0m\n\u001b[38;2;144;107;255m  GGGG         GGG     NN     GG#**Wp      @G\u001b[0m\n\u001b[38;2;144;107;255m  @GGGb       !GGG     GG     Gf    'G     !G[\u001b[0m\n\u001b[38;2;128;86;255m  'GGGG       #GGG     GG     Gb     `     $G`\u001b[0m\n\u001b[38;2;128;86;255m   @GGGb     iGGGG     GG     GGb        ,#G\"\u001b[0m\n\u001b[38;2;128;86;255m    @GGGG###G#@GGGG###GGGG###GGGGG######G#\"\u001b[0m\n\u001b[38;2;128;86;255m     `\"%N>\"     \"%NW\" `\"%NW\"   \"*%NlN*\"`\u001b[0m\n"
  },
  {
    "path": "examples/neofetch/vhs.ascii",
    "content": "     .--.   .--.   .-.   ,.-.     ,.-s-.\n ,p#G*\"\"TG#Gf\"\"*GG#\"\"\"@###\"\"\"$#p#GW\"\"^\"\"%G#,\n{GGG      Gp     G     GG     GG^         \"G#\n@GGG[     G     ]G     GG     Gf     N     @G\n'GGGG     G     #G     GG     Gb     %b    #G\n GGGG     @     GG            GG       \"$GGf\n ]GGG#    '    lGG            GGGN,      `@#,\n  GGGG         GGG     NN     GG#**Wp      @G\n  @GGGb       !GGG     GG     Gf    'G     !G[\n  'GGGG       #GGG     GG     Gb     `     $G`\n   @GGGb     iGGGG     GG     GGb        ,#G\"\n    @GGGG###G#@GGGG###GGGG###GGGGG######G#\"\n     `\"%N>\"     \"%NW\" `\"%NW\"   \"*%NlN*\"`"
  },
  {
    "path": "examples/neofetch/vhs.conf",
    "content": "print_info () {\n    prin\n    prin \"$(color 5)charmbracelet/vhs\"\n    prin\n    prin \"$(color 2)OS\" \"Video Home System\"\n    prin \"$(color 2)Packages\" \"(2) tree-sitter-vhs, vhs-action\"\n    prin \"$(color 2)Shell\" \"bash 5.2\"\n    prin \"$(color 2)Resolution\" \"1200x600\"\n    info \"Theme\" theme\n    info \"Icons\" icons\n    prin \"$(color 2)Terminal\" \"xterm.js\"\n    prin \"$(color 2)Font\" \"JetBrains Mono\"\n    prin \"$(color 2)Format\" \"Graphics Interchange\"\n\n    info cols\n}\n\nimage_source=\"$(cat ~/.config/neofetch/vhs-color.ascii)\"\ngap=-18\n"
  },
  {
    "path": "examples/publish/cassette.tape",
    "content": "Output output.gif\n\nType \"Hello from https://vhs.charm.sh!\"\n\nSleep 1s\n"
  },
  {
    "path": "examples/publish/publish.tape",
    "content": "Output publish.gif\nSet FontSize 20\n\nType 'vhs cassette.tape --publish'\nSleep 0.5s\nEnter\nSleep 10s\n"
  },
  {
    "path": "examples/screenshot.tape",
    "content": "Output examples/screenshot.gif\n\nSet FontSize 32\n\nType \"echo 'Hello world'\"\nEnter\nSleep 500ms\n\nScreenshot examples/hello_world.png\n\nType \"echo 'See your screenshot: examples/hello_world.png'\"\nEnter\nSleep 1.5s\n"
  },
  {
    "path": "examples/settings/README.md",
    "content": "# Settings\n\n### Width\n\n<img width=\"600\" src=\"./width.gif\" />\n\n\n```\nOutput examples/settings/width.gif\n\nSet Height 200\nSet Width 475\n\nType \"I'm a little teapot\"\n\nSleep 1s\n```\n\n### Height\n\n<img width=\"600\" src=\"./height.gif\" />\n\n```\nOutput examples/settings/height.gif\n\nSet Height 1000\nSet Width 1000\nSet FontSize 50\n\nType \"I'm a big teapot\"\n\nSleep 1s\n```\n\n### Font Family\n\n<img width=\"600\" src=\"./set-font-family.gif\" />\n\n```\nOutput examples/settings/set-font-family.gif\n\nSet FontSize 42\nSet Height 225\nSet FontFamily \"Monoflow\"\n\nType \"One moment please...\"\n\nSleep 0.5s\n```\n\n### Font Size\n\n<img width=\"600\" src=\"./set-font-size-10.gif\" />\n<img width=\"600\" src=\"./set-font-size-20.gif\" />\n<img width=\"600\" src=\"./set-font-size-40.gif\" />\n\n```\nOutput examples/settings/set-font-size-10.gif\n\nSet Height 225\n\nSet FontSize 10\n\nType \"Super Mushroom!!!\"\n\nSleep 1\n```\n\n### Letter Spacing\n\n<img width=\"600\" src=\"./set-letter-spacing.gif\" />\n\n```\nOutput examples/settings/set-letter-spacing.gif\nSet FontSize 42\nSet Height 225\nSet LetterSpacing 20\n\nType \"Smooooooooooooth\"\n\nSleep 2\n```\n\n### Line Height\n\n<img width=\"600\" src=\"./set-line-height.gif\" />\n\n```\nOutput examples/settings/set-line-height.gif\nSet Height 400\nSet FontSize 32\nSet LineHeight 1.8\n\nType \"Stay far away!\"\nSleep .5\nEnter\nSleep 1\n```\n\n### Padding\n\n<img width=\"600\" src=\"./set-padding.gif\" />\n\n```\nOutput examples/settings/set-padding.gif\nSet FontSize 32\nSet Height 150\nSet Padding 0\n\nType \"I'm so edgy!\"\nSleep 1\n```\n\n### Margins\n\n<img width=\"600\" src=\"./set-margin.gif\">\n\n```\nOutput \"examples/settings/set-margin.gif\"\nSet FontSize 20\nSet Width 600\nSet Height 300\nSet Padding 20\n\n# You can also use an image:\n# Set MarginFill \"path/to/image.png\"\nSet MarginFill \"#79B8C3\"\nSet Margin 20\n\nType \"I'm on top of an image!\"\nSleep 2s\n```\n\n\n### Window Bars\n\n<img width=\"600\" src=\"./set-bar.gif\">\n\n```\nOutput \"examples/settings/set-bar.gif\"\nSet FontSize 25\nSet Width 600\nSet Height 300\nSet Padding 20\n\nSet WindowBar Colorful\nSet WindowBarSize 40\n\nType \"I have a bar!\"\nSleep 2s\n```\n\n\n### Border Radius\n\n<img width=\"600\" src=\"./set-border-radius.gif\">\n\n```\nOutput \"examples/settings/set-border-radius.gif\"\nSet FontSize 25\nSet Width 600\nSet Height 300\nSet Padding 20\n\nSet MarginFill \"#79B8C3\"\nSet Margin 20\n\nSet BorderRadius 20\n\nType \"I have round corners.\"\nSleep 2s\n```\n\n\n### Theme\n\n<img width=\"600\" src=\"./set-theme.gif\" />\n\n```\nOutput examples/settings/set-theme.gif\nSet FontSize 42\nSet Height 225\nSet Theme { \"name\": \"Whimsy\", \"black\": \"#535178\", \"red\": \"#ef6487\", \"green\": \"#5eca89\", \"yellow\": \"#fdd877\", \"blue\": \"#65aef7\", \"purple\": \"#aa7ff0\", \"cyan\": \"#43c1be\", \"white\": \"#ffffff\", \"brightBlack\": \"#535178\", \"brightRed\": \"#ef6487\", \"brightGreen\": \"#5eca89\", \"brightYellow\": \"#fdd877\", \"brightBlue\": \"#65aef7\", \"brightPurple\": \"#aa7ff0\", \"brightCyan\": \"#43c1be\", \"brightWhite\": \"#ffffff\", \"background\": \"#29283b\", \"foreground\": \"#b3b0d6\", \"selectionBackground\": \"#3d3c58\", \"cursorAccent\": \"#b3b0d6\", \"cursor\": \"#b3b0d6\" }\n\nType \"I can't make up my mind.\"\nSleep 1\n```\n\n### Typing Speed\n\n<img width=\"600\" src=\"./set-typing-speed.gif\" />\n\n```\nOutput examples/settings/set-typing-speed.gif\nSet Height 400\nSet FontSize 32\n\nSet TypingSpeed 25ms\nType \"Bunny\"\nCtrl+C\nSet TypingSpeed 50ms\nType \"Human\"\nCtrl+C\nSet TypingSpeed 100ms\nType \"Tortoise\"\nCtrl+C\nType@250ms \"Sloth\"\nCtrl+C\nSleep 1\n```\n"
  },
  {
    "path": "examples/settings/height.tape",
    "content": "Output examples/settings/height.gif\n\nSet Height 1000\nSet Width 1000\nSet FontSize 50\n\nType \"I'm a big teapot\"\n\nSleep 1s\n"
  },
  {
    "path": "examples/settings/set-border-radius.tape",
    "content": "Output examples/settings/set-border-radius.gif\nSet FontSize 32\nSet Width 800\nSet Height 400\nSet Padding 30\n\nSet MarginFill \"#674EFF\"\nSet Margin 40\nSet BorderRadius 14\n\nType \"I hate sharp edges.\"\nSleep 2s"
  },
  {
    "path": "examples/settings/set-cursor-blink.tape",
    "content": "Output examples/settings/set-cursor-blink.gif\nSet FontSize 42\nSet Height 225\nSet CursorBlink false\n\nType \"Never blink...\"\n\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-font-family.tape",
    "content": "Output examples/settings/set-font-family.gif\n\nSet FontSize 42\nSet Height 225\nSet FontFamily \"Monoflow\"\n\nType \"One moment please...\"\n\nSleep 0.5s\n"
  },
  {
    "path": "examples/settings/set-font-size-10.tape",
    "content": "Output examples/settings/set-font-size-10.gif\n\nSet Height 225\n\nSet FontSize 10\n\nType \"Super Mushroom!!!\"\n\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-font-size-20.tape",
    "content": "Output examples/settings/set-font-size-20.gif\n\nSet Height 225\n\nSet FontSize 20\n\nType \"Super Mushroom!!!\"\n\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-font-size-40.tape",
    "content": "Output examples/settings/set-font-size-40.gif\n\nSet Height 225\n\nSet FontSize 40\n\nType \"Super Mushroom!!!\"\n\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-letter-spacing.tape",
    "content": "Output examples/settings/set-letter-spacing.gif\nSet FontSize 42\nSet Height 225\nSet LetterSpacing 20\n\nType \"Smooooooooooooth\"\n\nSleep 2\n"
  },
  {
    "path": "examples/settings/set-line-height.tape",
    "content": "Output examples/settings/set-line-height.gif\nSet Height 400\nSet FontSize 32\nSet LineHeight 1.8\n\nType \"Stay far away!\"\nSleep .5\nEnter\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-loop-offset.tape",
    "content": "Output examples/settings/set-loop-offset.gif\n\nSet FontSize 40\nSet LoopOffset 50% # % is optional\n\nType \"Round and 'round we go \\\" Enter\nSleep 1s\n\nType \"Round and 'round we go \\\" Enter\nSleep 1s\n\n# GIF will start here\n\nType \"Round and 'round we go \\\" Enter\nSleep 1s\n\nType \"Round and 'round we go \\\" Enter\nSleep 1s\n\n"
  },
  {
    "path": "examples/settings/set-margin.tape",
    "content": "Output examples/settings/set-margin.gif\n\nSet FontSize 24\nSet Width 800\nSet Height 400\nSet Padding 40\n\nSet Margin 60\nSet MarginFill \"#6B50FF\"\n\nType \"I have some margin! \\\" Enter\nType \"Do you want some?\"\nSleep 2s"
  },
  {
    "path": "examples/settings/set-padding.tape",
    "content": "Output examples/settings/set-padding.gif\nSet FontSize 32\nSet Height 150\nSet Padding 0\n\nType \"I'm so edgy!\"\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-shell-bash.tape",
    "content": "Output examples/settings/set-shell-bash.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell bash\n\nSleep 1s\nType \"I am using BASH.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-cmd.tape",
    "content": "Output examples/settings/set-shell-cmd.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell cmd\n\nSleep 1s\nType \"I am using CMD.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-custom.tape",
    "content": "Output examples/settings/set-shell-custom.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell ksh\n\nSleep 1s\nType \"I am using KSH.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-fish.tape",
    "content": "Output examples/settings/set-shell-fish.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell fish\n\nSleep 1s\nType \"I am using the friendly interactive shell\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-nu.tape",
    "content": "Output examples/settings/set-shell-nu.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell nu\n\nSleep 1s\nType \"I am using nu.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-osh.tape",
    "content": "Output examples/settings/set-shell-osh.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell osh\n\nSleep 1s\nType \"I am using OSH.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-pwsh.tape",
    "content": "Output examples/settings/set-shell-pwsh.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell pwsh\n\nSleep 1s\nType \"I am using PWSH.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-xonsh.tape",
    "content": "Output examples/settings/set-shell-xonsh.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell xonsh\n\nSleep 1s\nType \"I am using xonsh.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-shell-zsh.tape",
    "content": "Output examples/settings/set-shell-zsh.gif\n\nSet FontSize 38\nSet Height 225\n\nSet Shell zsh\n\nSleep 1s\nType \"I am using ZSH.\"\nSleep 2s\n"
  },
  {
    "path": "examples/settings/set-theme-name.tape",
    "content": "Output examples/settings/set-theme-name.gif\nSet FontSize 42\nSet Height 225\nSet Theme \"Catppuccin Latte\"\n\nType \"I can't make up my mind.\"\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-theme.tape",
    "content": "Output examples/settings/set-theme.gif\nSet FontSize 42\nSet Height 225\nSet Theme { \"name\": \"Whimsy\", \"black\": \"#535178\", \"red\": \"#ef6487\", \"green\": \"#5eca89\", \"yellow\": \"#fdd877\", \"blue\": \"#65aef7\", \"purple\": \"#aa7ff0\", \"cyan\": \"#43c1be\", \"white\": \"#ffffff\", \"brightBlack\": \"#535178\", \"brightRed\": \"#ef6487\", \"brightGreen\": \"#5eca89\", \"brightYellow\": \"#fdd877\", \"brightBlue\": \"#65aef7\", \"brightPurple\": \"#aa7ff0\", \"brightCyan\": \"#43c1be\", \"brightWhite\": \"#ffffff\", \"background\": \"#29283b\", \"foreground\": \"#b3b0d6\", \"selectionBackground\": \"#3d3c58\", \"cursorAccent\": \"#b3b0d6\", \"cursor\": \"#b3b0d6\" }\n\nType \"I can't make up my mind.\"\nSleep 1\n"
  },
  {
    "path": "examples/settings/set-typing-speed.tape",
    "content": "Output examples/settings/set-typing-speed.gif\nSet Height 400\nSet FontSize 32\n\nSet TypingSpeed 25ms\nType \"Bunny\"\nCtrl+C\nSet TypingSpeed 50ms\nType \"Human\"\nCtrl+C\nSet TypingSpeed 100ms\nType \"Tortoise\"\nCtrl+C\nType@250ms \"Sloth\"\nCtrl+C\nSleep 1"
  },
  {
    "path": "examples/settings/set-window-bar.tape",
    "content": "Output examples/settings/set-window-bar.gif\n\nSet FontSize 25\nSet Width 800\nSet Height 400\nSet Padding 20\n\nSet WindowBar Colorful\nSet WindowBarSize 40\n\nType \"This terminal has window controls.\"\nSleep 2s"
  },
  {
    "path": "examples/settings/width.tape",
    "content": "Output examples/settings/width.gif\n\nSet Height 200\nSet Width 475\n\nType \"I'm a little teapot\"\n\nSleep 1s\n"
  },
  {
    "path": "examples/slides/README.md",
    "content": "# Slides\n\n<img width=\"600\" src=\"./slides.gif\" />\n\n```\nOutput examples/slides/slides.gif\nSet FontSize 32\nSet Padding 0\nSet Framerate 1\nSet Width 1600\nSet Height 1200\n\nHide\nType \"slides\"\nEnter\nShow\n\nSleep 1s\n\nType@1s \"n\"\n\nSleep 1s\n\nCtrl+E\n\nSleep 1s\n\nType@1s \"nnn\"\n\nSleep 1s\n```\n"
  },
  {
    "path": "examples/slides/slides.tape",
    "content": "Output examples/slides/slides.gif\nSet FontSize 32\nSet Padding 0\nSet Framerate 1\nSet Width 1600\nSet Height 1200\n\nHide\nType \"slides\"\nEnter\nShow\n\nSleep 1s\n\nType@1s \"n\"\n\nSleep 1s\n\nCtrl+E\n\nSleep 1s\n\nType@1s \"nnn\"\n\nSleep 1s\n"
  },
  {
    "path": "examples/split/split.tape",
    "content": "Output split.gif\n\nRequire tmux\n\nHide\n  Type \"tmux -f /dev/null -L test new-session -- bash\" Enter\n  Type \"tmux split-window -d -h -- bash && \\\" Enter\n  Type \"tmux set status && \\\" Enter\n  Type 'tmux setw pane-border-style \"fg=0\" && \\' Enter\n  Type 'tmux setw pane-active-border-style \"fg=0\"' Enter\n  Sleep 0.5\n  Ctrl+L\n  Sleep 1\nShow\n\nType \"Window 1\"\nSleep 1\n\n# tmux bind to switch to next pane\nCtrl+B\nType o\n\nSleep 1\nType \"Window 2\"\nSleep 1\n"
  },
  {
    "path": "examples/vhs-promo.webm",
    "content": "version https://git-lfs.github.com/spec/v1\noid sha256:2efe4b93955fcc08abcd4c472c3652f3defcdfbd6c42997e48a7204605d3ebd8\nsize 238435\n"
  },
  {
    "path": "examples/welcome.tape",
    "content": "# Render the output GIF to demo.gif\nOutput examples/welcome.gif\nOutput examples/frames/\n\n# Set up a 1200x600 frame with 46px font size.\nSet FontSize 46\nSet Height 600\nSet Width 1200\nSet TypingSpeed 40ms\n\nType \"Welcome to VHS!\"\nSleep 0.5s\nCtrl+C\nSleep 0.5s\n\nType \"A tool for writing GIFs as code.\"\nSleep 0.5s\nLeft 14\nSleep 0.5s\nType \" terminal\"\nSleep 1s\nCtrl+E\nSleep 0.5s\nCtrl+U\nSleep 0.5s\n\nType 'echo \"Demo your CLIs and TUIs.\"'\nSleep 0.5s\nEnter\nSleep 0.5s\n\nType \"Let's take it for a spin\"\nLeft 5\n\nSleep 0.5s\nCtrl+U\nSleep 0.5s\nType \"gum\"\n\nSleep 0.5s\nCtrl+E\nSleep 0.5s\n\nType \" -s line -- sleep 2.5\"\nSleep 0.5s\nEnter\n\nSleep 3s\n\nType \"clear\"\n\nSleep 0.5s\n\nEnter\n"
  },
  {
    "path": "ffmpeg.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\n// FilterComplexBuilder generates -filter_complex option of ffmepg.\ntype FilterComplexBuilder struct {\n\tfilterComplex *strings.Builder\n\tstyle         *StyleOptions\n\ttermWidth     int\n\ttermHeight    int\n\tprevStageName string\n}\n\n// NewVideoFilterBuilder returns instance of FilterComplexBuilder with video config.\nfunc NewVideoFilterBuilder(videoOpts *VideoOptions) *FilterComplexBuilder {\n\tfilterCode := strings.Builder{}\n\ttermWidth, termHeight := calcTermDimensions(*videoOpts.Style)\n\n\t_, _ = fmt.Fprintf(&filterCode, `\n\t\t[0][1]overlay[merged];\n\t\t[merged]scale=%d:%d:force_original_aspect_ratio=1[scaled];\n\t\t[scaled]fps=%d,setpts=PTS/%f[speed];\n\t\t[speed]pad=%d:%d:(ow-iw)/2:(oh-ih)/2:%s[padded];\n\t\t[padded]fillborders=left=%d:right=%d:top=%d:bottom=%d:mode=fixed:color=%s[padded]\n\t\t`,\n\t\ttermWidth-double(videoOpts.Style.Padding),\n\t\ttermHeight-double(videoOpts.Style.Padding),\n\n\t\tvideoOpts.Framerate,\n\t\tvideoOpts.PlaybackSpeed,\n\n\t\ttermWidth,\n\t\ttermHeight,\n\t\tvideoOpts.Style.BackgroundColor,\n\n\t\tvideoOpts.Style.Padding,\n\t\tvideoOpts.Style.Padding,\n\t\tvideoOpts.Style.Padding,\n\t\tvideoOpts.Style.Padding,\n\t\tvideoOpts.Style.BackgroundColor,\n\t)\n\n\treturn &FilterComplexBuilder{\n\t\tfilterComplex: &filterCode,\n\t\ttermHeight:    termHeight,\n\t\ttermWidth:     termWidth,\n\t\tstyle:         videoOpts.Style,\n\t\tprevStageName: \"padded\",\n\t}\n}\n\n// NewScreenshotFilterComplexBuilder returns instance of FilterComplexBuilder with screenshot config.\nfunc NewScreenshotFilterComplexBuilder(style *StyleOptions) *FilterComplexBuilder {\n\tfilterCode := strings.Builder{}\n\ttermWidth, termHeight := calcTermDimensions(*style)\n\n\t_, _ = fmt.Fprintf(&filterCode, `\n\t\t[0][1]overlay[merged];\n\t\t[merged]scale=%d:%d:force_original_aspect_ratio=1[scaled];\n\t\t[scaled]pad=%d:%d:(ow-iw)/2:(oh-ih)/2:%s[padded];\n\t\t[padded]fillborders=left=%d:right=%d:top=%d:bottom=%d:mode=fixed:color=%s[padded]\n\t\t`,\n\t\ttermWidth-double(style.Padding),\n\t\ttermHeight-double(style.Padding),\n\n\t\ttermWidth,\n\t\ttermHeight,\n\t\tstyle.BackgroundColor,\n\n\t\tstyle.Padding,\n\t\tstyle.Padding,\n\t\tstyle.Padding,\n\t\tstyle.Padding,\n\t\tstyle.BackgroundColor,\n\t)\n\n\treturn &FilterComplexBuilder{\n\t\tfilterComplex: &filterCode,\n\t\ttermHeight:    termHeight,\n\t\ttermWidth:     termWidth,\n\t\tstyle:         style,\n\t\tprevStageName: \"padded\",\n\t}\n}\n\n// calcTermDimensions computes terminal dimensions.\n// It returns width and height values.\nfunc calcTermDimensions(style StyleOptions) (int, int) {\n\twidth := style.Width\n\theight := style.Height\n\tif style.MarginFill != \"\" {\n\t\twidth = width - double(style.Margin)\n\t\theight = height - double(style.Margin)\n\t}\n\tif style.WindowBar != \"\" {\n\t\theight = height - style.WindowBarSize\n\t}\n\n\treturn width, height\n}\n\n// WithWindowBar adds window bar options to ffmepg filter_complex.\nfunc (fb *FilterComplexBuilder) WithWindowBar(barStream int) *FilterComplexBuilder {\n\tif fb.style.WindowBar != \"\" {\n\t\tfb.filterComplex.WriteString(\";\")\n\t\t_, _ = fmt.Fprintf(\n\t\t\tfb.filterComplex,\n\t\t\t`\n\t\t\t[%d]loop=-1[loopbar];\n\t\t\t[loopbar][%s]overlay=0:%d[withbar]\n\t\t\t`,\n\t\t\tbarStream,\n\t\t\tfb.prevStageName,\n\t\t\tfb.style.WindowBarSize,\n\t\t)\n\n\t\tfb.prevStageName = \"withbar\"\n\t}\n\n\treturn fb\n}\n\n// WithBorderRadius adds border radius options to ffmepg filter_complex.\nfunc (fb *FilterComplexBuilder) WithBorderRadius(cornerMarkStream int) *FilterComplexBuilder {\n\tif fb.style.BorderRadius != 0 {\n\t\tfb.filterComplex.WriteString(\";\")\n\t\t_, _ = fmt.Fprintf(\n\t\t\tfb.filterComplex,\n\t\t\t`\n\t\t\t[%d]loop=-1[loopmask];\n\t\t\t[%s][loopmask]alphamerge[rounded]\n\t\t\t`,\n\t\t\tcornerMarkStream,\n\t\t\tfb.prevStageName,\n\t\t)\n\t\tfb.prevStageName = \"rounded\"\n\t}\n\n\treturn fb\n}\n\n// WithMarginFill adds margin options to ffmepg filter_complex.\nfunc (fb *FilterComplexBuilder) WithMarginFill(marginStream int) *FilterComplexBuilder {\n\t// Overlay terminal on margin\n\tif fb.style.MarginFill != \"\" {\n\t\t// ffmpeg will complain if the final filter ends with a semicolon,\n\t\t// so we add one BEFORE we start adding filters.\n\t\tfb.filterComplex.WriteString(\";\")\n\t\t_, _ = fmt.Fprintf(\n\t\t\tfb.filterComplex,\n\t\t\t`\n\t\t\t[%d]scale=%d:%d[bg];\n\t\t\t[bg][%s]overlay=(W-w)/2:(H-h)/2:shortest=1[withbg]\n\t\t\t`,\n\t\t\tmarginStream,\n\t\t\tfb.style.Width,\n\t\t\tfb.style.Height,\n\t\t\tfb.prevStageName,\n\t\t)\n\t\tfb.prevStageName = \"withbg\"\n\t}\n\n\treturn fb\n}\n\n// WithGIF adds gif options to ffmepg filter_complex.\nfunc (fb *FilterComplexBuilder) WithGIF() *FilterComplexBuilder {\n\tfb.filterComplex.WriteString(\";\")\n\t_, _ = fmt.Fprintf(\n\t\tfb.filterComplex,\n\t\t`\n\t\t[%s]split[plt_a][plt_b];\n\t\t[plt_a]palettegen=max_colors=256[plt];\n\t\t[plt_b][plt]paletteuse[palette]`,\n\t\tfb.prevStageName,\n\t)\n\tfb.prevStageName = \"palette\"\n\n\treturn fb\n}\n\n// Build returns filter_complex used in ffmepg.\nfunc (fb *FilterComplexBuilder) Build() []string {\n\treturn []string{\n\t\t\"-filter_complex\", fb.filterComplex.String(),\n\t\t\"-map\", \"[\" + fb.prevStageName + \"]\",\n\t}\n}\n\n// StreamBuilder generates streams used by ffmepg.\ntype StreamBuilder struct {\n\targs         []string\n\tcounter      int\n\tstyle        *StyleOptions\n\ttermWidth    int\n\ttermHeight   int\n\tinput        string\n\tbarStream    int\n\tcornerStream int\n\tmarginStream int\n}\n\n// NewStreamBuilder returns instance of StreamBuilder.\nfunc NewStreamBuilder(streamCounter int, input string, style *StyleOptions) *StreamBuilder {\n\ttermWidth, termHeight := calcTermDimensions(*style)\n\n\treturn &StreamBuilder{\n\t\tcounter:    streamCounter,\n\t\targs:       []string{},\n\t\tstyle:      style,\n\t\ttermWidth:  termWidth,\n\t\ttermHeight: termHeight,\n\t\tinput:      input,\n\t}\n}\n\n// WithMargin adds margin stream.\nfunc (sb *StreamBuilder) WithMargin() *StreamBuilder {\n\tif sb.style.MarginFill != \"\" {\n\t\tif marginFillIsColor(sb.style.MarginFill) {\n\t\t\t// Create plain color stream\n\t\t\tsb.args = append(sb.args,\n\t\t\t\t\"-f\", \"lavfi\",\n\t\t\t\t\"-i\",\n\t\t\t\tfmt.Sprintf(\n\t\t\t\t\t\"color=%s:s=%dx%d\",\n\t\t\t\t\tsb.style.MarginFill,\n\t\t\t\t\tsb.style.Width,\n\t\t\t\t\tsb.style.Height,\n\t\t\t\t),\n\t\t\t)\n\t\t} else {\n\t\t\t// Check for existence first.\n\t\t\t_, err := os.Stat(sb.style.MarginFill)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(ErrorStyle.Render(\"Unable to read margin file: \"), sb.style.MarginFill)\n\t\t\t}\n\n\t\t\t// Add image stream\n\t\t\tsb.args = append(sb.args,\n\t\t\t\t\"-loop\", \"1\",\n\t\t\t\t\"-i\", sb.style.MarginFill,\n\t\t\t)\n\t\t}\n\n\t\tsb.marginStream = sb.counter\n\t\tsb.counter++\n\t}\n\n\treturn sb\n}\n\n// WithBar adds bar stream.\nfunc (sb *StreamBuilder) WithBar() *StreamBuilder {\n\tbarPath := filepath.Join(sb.input, \"bar.png\")\n\n\tif sb.style.WindowBar != \"\" {\n\t\tMakeWindowBar(sb.termWidth, sb.termHeight, *sb.style, barPath)\n\n\t\tsb.args = append(sb.args,\n\t\t\t\"-i\", barPath,\n\t\t)\n\n\t\tsb.barStream = sb.counter\n\t\tsb.counter++\n\t}\n\n\treturn sb\n}\n\n// WithCorner adds corner stream.\nfunc (sb *StreamBuilder) WithCorner() *StreamBuilder {\n\tmaskPath := filepath.Join(sb.input, \"mask.png\")\n\n\tif sb.style.BorderRadius != 0 {\n\t\tif sb.style.WindowBar != \"\" {\n\t\t\tMakeBorderRadiusMask(sb.termWidth, sb.termHeight+sb.style.WindowBarSize, sb.style.BorderRadius, maskPath)\n\t\t} else {\n\t\t\tMakeBorderRadiusMask(sb.termWidth, sb.termHeight, sb.style.BorderRadius, maskPath)\n\t\t}\n\n\t\tsb.args = append(sb.args,\n\t\t\t\"-i\", maskPath,\n\t\t)\n\n\t\tsb.cornerStream = sb.counter\n\t\tsb.counter++\n\t}\n\n\treturn sb\n}\n\n// WithMP4 adds mp4 stream with required config.\nfunc (sb *StreamBuilder) WithMP4() *StreamBuilder {\n\tsb.args = append(sb.args,\n\t\t\"-vcodec\", \"libx264\",\n\t\t\"-pix_fmt\", \"yuv420p\",\n\t\t\"-an\",\n\t\t\"-crf\", \"20\",\n\t)\n\n\treturn sb\n}\n\n// WithWebm adds webm stream with required config.\nfunc (sb *StreamBuilder) WithWebm() *StreamBuilder {\n\tsb.args = append(sb.args,\n\t\t\"-pix_fmt\", \"yuv420p\",\n\t\t\"-an\",\n\t\t\"-crf\", \"30\",\n\t\t\"-b:v\", \"0\",\n\t)\n\treturn sb\n}\n\n// Build returns streams for using with ffmepg.\nfunc (sb *StreamBuilder) Build() []string {\n\treturn sb.args\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/charmbracelet/vhs\n\ngo 1.25.8\n\nrequire (\n\tgithub.com/agnivade/levenshtein v1.2.1\n\tgithub.com/atotto/clipboard v0.1.4\n\tgithub.com/caarlos0/env/v11 v11.4.0\n\tgithub.com/charmbracelet/glamour v1.0.0\n\tgithub.com/charmbracelet/keygen v0.5.4\n\tgithub.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834\n\tgithub.com/charmbracelet/ssh v0.0.0-20250128164007-98fd5ae11894\n\tgithub.com/charmbracelet/wish v1.4.7\n\tgithub.com/creack/pty v1.1.24\n\tgithub.com/go-rod/rod v0.116.2\n\tgithub.com/hashicorp/go-version v1.8.0\n\tgithub.com/mattn/go-isatty v0.0.20\n\tgithub.com/mattn/go-runewidth v0.0.21\n\tgithub.com/muesli/go-app-paths v0.2.2\n\tgithub.com/muesli/mango-cobra v1.3.0\n\tgithub.com/muesli/roff v0.1.0\n\tgithub.com/muesli/termenv v0.16.0\n\tgithub.com/spf13/cobra v1.10.2\n\tgolang.org/x/crypto v0.49.0\n\tgolang.org/x/term v0.41.0\n)\n\nrequire (\n\tgithub.com/alecthomas/chroma/v2 v2.20.0 // indirect\n\tgithub.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect\n\tgithub.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect\n\tgithub.com/aymerick/douceur v0.2.0 // indirect\n\tgithub.com/charmbracelet/bubbletea v1.3.4 // indirect\n\tgithub.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect\n\tgithub.com/charmbracelet/log v0.4.1 // indirect\n\tgithub.com/charmbracelet/x/ansi v0.10.2 // indirect\n\tgithub.com/charmbracelet/x/cellbuf v0.0.13 // indirect\n\tgithub.com/charmbracelet/x/conpty v0.1.0 // indirect\n\tgithub.com/charmbracelet/x/errors v0.0.0-20240904165849-e8e43e13f84b // indirect\n\tgithub.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b // indirect\n\tgithub.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect\n\tgithub.com/charmbracelet/x/term v0.2.1 // indirect\n\tgithub.com/charmbracelet/x/termios v0.1.0 // indirect\n\tgithub.com/clipperhouse/uax29/v2 v2.2.0 // indirect\n\tgithub.com/dlclark/regexp2 v1.11.5 // indirect\n\tgithub.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect\n\tgithub.com/go-logfmt/logfmt v0.6.0 // indirect\n\tgithub.com/gorilla/css v1.0.1 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/lucasb-eyer/go-colorful v1.3.0 // indirect\n\tgithub.com/mattn/go-localereader v0.0.1 // indirect\n\tgithub.com/microcosm-cc/bluemonday v1.0.27 // indirect\n\tgithub.com/mitchellh/go-homedir v1.1.0 // indirect\n\tgithub.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect\n\tgithub.com/muesli/cancelreader v0.2.2 // indirect\n\tgithub.com/muesli/mango v0.2.0 // indirect\n\tgithub.com/muesli/mango-pflag v0.1.0 // indirect\n\tgithub.com/muesli/reflow v0.3.0 // indirect\n\tgithub.com/rivo/uniseg v0.4.7 // indirect\n\tgithub.com/spf13/pflag v1.0.9 // indirect\n\tgithub.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect\n\tgithub.com/ysmood/fetchup v0.2.3 // indirect\n\tgithub.com/ysmood/goob v0.4.0 // indirect\n\tgithub.com/ysmood/got v0.40.0 // indirect\n\tgithub.com/ysmood/gson v0.7.3 // indirect\n\tgithub.com/ysmood/leakless v0.9.0 // indirect\n\tgithub.com/yuin/goldmark v1.7.13 // indirect\n\tgithub.com/yuin/goldmark-emoji v1.0.6 // indirect\n\tgolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect\n\tgolang.org/x/net v0.51.0 // indirect\n\tgolang.org/x/sync v0.20.0 // indirect\n\tgolang.org/x/sys v0.42.0 // indirect\n\tgolang.org/x/text v0.35.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=\ngithub.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=\ngithub.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=\ngithub.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=\ngithub.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw=\ngithub.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA=\ngithub.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg=\ngithub.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=\ngithub.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=\ngithub.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=\ngithub.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=\ngithub.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=\ngithub.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=\ngithub.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=\ngithub.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=\ngithub.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=\ngithub.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=\ngithub.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=\ngithub.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=\ngithub.com/caarlos0/env/v11 v11.4.0 h1:Kcb6t5kIIr4XkoQC9AF2j+8E1Jsrl3Wz/hhm1LtoGAc=\ngithub.com/caarlos0/env/v11 v11.4.0/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U=\ngithub.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI=\ngithub.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=\ngithub.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=\ngithub.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=\ngithub.com/charmbracelet/glamour v1.0.0 h1:AWMLOVFHTsysl4WV8T8QgkQ0s/ZNZo7CiE4WKhk8l08=\ngithub.com/charmbracelet/glamour v1.0.0/go.mod h1:DSdohgOBkMr2ZQNhw4LZxSGpx3SvpeujNoXrQyH2hxo=\ngithub.com/charmbracelet/keygen v0.5.4 h1:XQYgf6UEaTGgQSSmiPpIQ78WfseNQp4Pz8N/c1OsrdA=\ngithub.com/charmbracelet/keygen v0.5.4/go.mod h1:t4oBRr41bvK7FaJsAaAQhhkUuHslzFXVjOBwA55CZNM=\ngithub.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE=\ngithub.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA=\ngithub.com/charmbracelet/log v0.4.1 h1:6AYnoHKADkghm/vt4neaNEXkxcXLSV2g1rdyFDOpTyk=\ngithub.com/charmbracelet/log v0.4.1/go.mod h1:pXgyTsqsVu4N9hGdHmQ0xEA4RsXof402LX9ZgiITn2I=\ngithub.com/charmbracelet/ssh v0.0.0-20250128164007-98fd5ae11894 h1:Ffon9TbltLGBsT6XE//YvNuu4OAaThXioqalhH11xEw=\ngithub.com/charmbracelet/ssh v0.0.0-20250128164007-98fd5ae11894/go.mod h1:hg+I6gvlMl16nS9ZzQNgBIrrCasGwEw0QiLsDcP01Ko=\ngithub.com/charmbracelet/wish v1.4.7 h1:O+jdLac3s6GaqkOHHSwezejNK04vl6VjO1A+hl8J8Yc=\ngithub.com/charmbracelet/wish v1.4.7/go.mod h1:OBZ8vC62JC5cvbxJLh+bIWtG7Ctmct+ewziuUWK+G14=\ngithub.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw=\ngithub.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=\ngithub.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=\ngithub.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=\ngithub.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U=\ngithub.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ=\ngithub.com/charmbracelet/x/errors v0.0.0-20240904165849-e8e43e13f84b h1:mRcbrwMt9VQa1LW/Q3Vty0nricT8TdiEDAX+A2bZVMM=\ngithub.com/charmbracelet/x/errors v0.0.0-20240904165849-e8e43e13f84b/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=\ngithub.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=\ngithub.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=\ngithub.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI=\ngithub.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU=\ngithub.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=\ngithub.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=\ngithub.com/charmbracelet/x/termios v0.1.0 h1:y4rjAHeFksBAfGbkRDmVinMg7x7DELIGAFbdNvxg97k=\ngithub.com/charmbracelet/x/termios v0.1.0/go.mod h1:H/EVv/KRnrYjz+fCYa9bsKdqF3S8ouDK0AZEbG7r+/U=\ngithub.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY=\ngithub.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=\ngithub.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=\ngithub.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo=\ngithub.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=\ngithub.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=\ngithub.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=\ngithub.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=\ngithub.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=\ngithub.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=\ngithub.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=\ngithub.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA=\ngithub.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg=\ngithub.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=\ngithub.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=\ngithub.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=\ngithub.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=\ngithub.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=\ngithub.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=\ngithub.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=\ngithub.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=\ngithub.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=\ngithub.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=\ngithub.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=\ngithub.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=\ngithub.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=\ngithub.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=\ngithub.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=\ngithub.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=\ngithub.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=\ngithub.com/muesli/go-app-paths v0.2.2 h1:NqG4EEZwNIhBq/pREgfBmgDmt3h1Smr1MjZiXbpZUnI=\ngithub.com/muesli/go-app-paths v0.2.2/go.mod h1:SxS3Umca63pcFcLtbjVb+J0oD7cl4ixQWoBKhGEtEho=\ngithub.com/muesli/mango v0.2.0 h1:iNNc0c5VLQ6fsMgAqGQofByNUBH2Q2nEbD6TaI+5yyQ=\ngithub.com/muesli/mango v0.2.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4=\ngithub.com/muesli/mango-cobra v1.3.0 h1:vQy5GvPg3ndOSpduxutqFoINhWk3vD5K2dXo5E8pqec=\ngithub.com/muesli/mango-cobra v1.3.0/go.mod h1:Cj1ZrBu3806Qw7UjxnAUgE+7tllUBj1NCLQDwwGx19E=\ngithub.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg=\ngithub.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0=\ngithub.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=\ngithub.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=\ngithub.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=\ngithub.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=\ngithub.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=\ngithub.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=\ngithub.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=\ngithub.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=\ngithub.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=\ngithub.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=\ngithub.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=\ngithub.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=\ngithub.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=\ngithub.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=\ngithub.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=\ngithub.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=\ngithub.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=\ngithub.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18=\ngithub.com/ysmood/gop v0.2.0 h1:+tFrG0TWPxT6p9ZaZs+VY+opCvHU8/3Fk6BaNv6kqKg=\ngithub.com/ysmood/gop v0.2.0/go.mod h1:rr5z2z27oGEbyB787hpEcx4ab8cCiPnKxn0SUHt6xzk=\ngithub.com/ysmood/got v0.40.0 h1:ZQk1B55zIvS7zflRrkGfPDrPG3d7+JOza1ZkNxcc74Q=\ngithub.com/ysmood/got v0.40.0/go.mod h1:W7DdpuX6skL3NszLmAsC5hT7JAhuLZhByVzHTq874Qg=\ngithub.com/ysmood/gotrace v0.6.0 h1:SyI1d4jclswLhg7SWTL6os3L1WOKeNn/ZtzVQF8QmdY=\ngithub.com/ysmood/gotrace v0.6.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=\ngithub.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=\ngithub.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=\ngithub.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU=\ngithub.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=\ngithub.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=\ngithub.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=\ngithub.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs=\ngithub.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA=\ngo.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=\ngolang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=\ngolang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=\ngolang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=\ngolang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=\ngolang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=\ngolang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=\ngolang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=\ngolang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=\ngolang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=\ngolang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=\ngolang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=\ngolang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "keys.go",
    "content": "// Package vhs keys.go defines the key map for the Type command.\n// The `keymap` map is used to convert runes from a string into the appropriate\n// go-rod input.\n//\n// Type Hello, world!\n//\n// The above command will type the string \"Hello, world!\" into the terminal,\n// by converting each rune into the correct input.\n//\n// Hello, world!\n// { shift(input.KeyH), input.KeyE, ..., input.KeyD, shift(input.Digit1) }\npackage main\n\nimport (\n\t\"github.com/go-rod/rod/lib/input\"\n)\n\n// shift returns the input.Key with the shift modifier set.\nfunc shift(k input.Key) input.Key {\n\tk, _ = k.Shift()\n\treturn k\n}\n\n// keymap is the map of runes to input.Keys.\n// It is used to convert a string to the correct set of input.Keys for go-rod.\nvar keymap = map[rune]input.Key{\n\t' ':    input.Space,\n\t'!':    shift(input.Digit1),\n\t'\"':    shift(input.Quote),\n\t'#':    shift(input.Digit3),\n\t'$':    shift(input.Digit4),\n\t'%':    shift(input.Digit5),\n\t'&':    shift(input.Digit7),\n\t'(':    shift(input.Digit9),\n\t')':    shift(input.Digit0),\n\t'*':    shift(input.Digit8),\n\t'+':    shift(input.Equal),\n\t',':    input.Comma,\n\t'-':    input.Minus,\n\t'.':    input.Period,\n\t'/':    input.Slash,\n\t'0':    input.Digit0,\n\t'1':    input.Digit1,\n\t'2':    input.Digit2,\n\t'3':    input.Digit3,\n\t'4':    input.Digit4,\n\t'5':    input.Digit5,\n\t'6':    input.Digit6,\n\t'7':    input.Digit7,\n\t'8':    input.Digit8,\n\t'9':    input.Digit9,\n\t':':    shift(input.Semicolon),\n\t';':    input.Semicolon,\n\t'<':    shift(input.Comma),\n\t'=':    input.Equal,\n\t'>':    shift(input.Period),\n\t'?':    shift(input.Slash),\n\t'@':    shift(input.Digit2),\n\t'A':    shift(input.KeyA),\n\t'B':    shift(input.KeyB),\n\t'C':    shift(input.KeyC),\n\t'D':    shift(input.KeyD),\n\t'E':    shift(input.KeyE),\n\t'F':    shift(input.KeyF),\n\t'G':    shift(input.KeyG),\n\t'H':    shift(input.KeyH),\n\t'I':    shift(input.KeyI),\n\t'J':    shift(input.KeyJ),\n\t'K':    shift(input.KeyK),\n\t'L':    shift(input.KeyL),\n\t'M':    shift(input.KeyM),\n\t'N':    shift(input.KeyN),\n\t'O':    shift(input.KeyO),\n\t'P':    shift(input.KeyP),\n\t'Q':    shift(input.KeyQ),\n\t'R':    shift(input.KeyR),\n\t'S':    shift(input.KeyS),\n\t'T':    shift(input.KeyT),\n\t'U':    shift(input.KeyU),\n\t'V':    shift(input.KeyV),\n\t'W':    shift(input.KeyW),\n\t'X':    shift(input.KeyX),\n\t'Y':    shift(input.KeyY),\n\t'Z':    shift(input.KeyZ),\n\t'[':    input.BracketLeft,\n\t'\\'':   input.Quote,\n\t'\\\\':   input.Backslash,\n\t'\\b':   input.Backspace,\n\t'\\n':   input.Enter,\n\t'\\r':   input.Enter,\n\t'\\t':   input.Tab,\n\t'\\x1b': input.Escape,\n\t']':    input.BracketRight,\n\t'^':    shift(input.Digit6),\n\t'_':    shift(input.Minus),\n\t'`':    input.Backquote,\n\t'a':    input.KeyA,\n\t'b':    input.KeyB,\n\t'c':    input.KeyC,\n\t'd':    input.KeyD,\n\t'e':    input.KeyE,\n\t'f':    input.KeyF,\n\t'g':    input.KeyG,\n\t'h':    input.KeyH,\n\t'i':    input.KeyI,\n\t'j':    input.KeyJ,\n\t'k':    input.KeyK,\n\t'l':    input.KeyL,\n\t'm':    input.KeyM,\n\t'n':    input.KeyN,\n\t'o':    input.KeyO,\n\t'p':    input.KeyP,\n\t'q':    input.KeyQ,\n\t'r':    input.KeyR,\n\t's':    input.KeyS,\n\t't':    input.KeyT,\n\t'u':    input.KeyU,\n\t'v':    input.KeyV,\n\t'w':    input.KeyW,\n\t'x':    input.KeyX,\n\t'y':    input.KeyY,\n\t'z':    input.KeyZ,\n\t'{':    shift(input.BracketLeft),\n\t'|':    shift(input.Backslash),\n\t'}':    shift(input.BracketRight),\n\t'~':    shift(input.Backquote),\n\t'←':    input.ArrowLeft,\n\t'↑':    input.ArrowUp,\n\t'→':    input.ArrowRight,\n\t'↓':    input.ArrowDown,\n}\n"
  },
  {
    "path": "lexer/lexer.go",
    "content": "// Package lexer provides a lexer for the VHS Tape language.\npackage lexer\n\nimport \"github.com/charmbracelet/vhs/token\"\n\n// Lexer is a lexer that tokenizes the input.\ntype Lexer struct {\n\tch      byte\n\tinput   string\n\tpos     int\n\tnextPos int\n\tline    int\n\tcolumn  int\n}\n\n// New returns a new lexer for tokenizing the input string.\nfunc New(input string) *Lexer {\n\tl := &Lexer{input: input, line: 1, column: 0}\n\tl.readChar()\n\treturn l\n}\n\n// readChar advances the lexer to the next character.\nfunc (l *Lexer) readChar() {\n\tl.column++\n\tl.ch = l.peekChar()\n\tl.pos = l.nextPos\n\tl.nextPos++\n}\n\n// NextToken returns the next token in the input.\nfunc (l *Lexer) NextToken() token.Token {\n\tl.skipWhitespace()\n\n\ttok := token.Token{Line: l.line, Column: l.column}\n\n\tswitch l.ch {\n\tcase 0:\n\t\ttok = l.newToken(token.EOF, l.ch)\n\tcase '@':\n\t\ttok = l.newToken(token.AT, l.ch)\n\t\tl.readChar()\n\tcase '=':\n\t\ttok = l.newToken(token.EQUAL, l.ch)\n\t\tl.readChar()\n\tcase ']':\n\t\ttok = l.newToken(token.RIGHT_BRACKET, l.ch)\n\t\tl.readChar()\n\tcase '[':\n\t\ttok = l.newToken(token.LEFT_BRACKET, l.ch)\n\t\tl.readChar()\n\tcase '-':\n\t\ttok = l.newToken(token.MINUS, l.ch)\n\t\tl.readChar()\n\tcase '%':\n\t\ttok = l.newToken(token.PERCENT, l.ch)\n\t\tl.readChar()\n\tcase '^':\n\t\ttok = l.newToken(token.CARET, l.ch)\n\t\tl.readChar()\n\tcase '\\\\':\n\t\ttok = l.newToken(token.BACKSLASH, l.ch)\n\t\tl.readChar()\n\tcase '#':\n\t\ttok.Type = token.COMMENT\n\t\ttok.Literal = l.readComment()\n\tcase '+':\n\t\ttok = l.newToken(token.PLUS, l.ch)\n\t\tl.readChar()\n\tcase '{':\n\t\ttok.Type = token.JSON\n\t\ttok.Literal = \"{\" + l.readJSON() + \"}\"\n\t\tl.readChar()\n\tcase '`':\n\t\ttok.Type = token.STRING\n\t\ttok.Literal = l.readString('`')\n\t\tl.readChar()\n\tcase '\\'':\n\t\ttok.Type = token.STRING\n\t\ttok.Literal = l.readString('\\'')\n\t\tl.readChar()\n\tcase '\"':\n\t\ttok.Type = token.STRING\n\t\ttok.Literal = l.readString('\"')\n\t\tl.readChar()\n\tcase '/':\n\t\ttok.Type = token.REGEX\n\t\ttok.Literal = l.readRegex('/')\n\t\tl.readChar()\n\tdefault:\n\t\tif isDigit(l.ch) || (isDot(l.ch) && isDigit(l.peekChar())) {\n\t\t\ttok.Literal = l.readNumber()\n\t\t\ttok.Type = token.NUMBER\n\t\t} else if isLetter(l.ch) || isDot(l.ch) {\n\t\t\ttok.Literal = l.readIdentifier()\n\t\t\ttok.Type = token.LookupIdentifier(tok.Literal)\n\t\t} else {\n\t\t\ttok = l.newToken(token.ILLEGAL, l.ch)\n\t\t\tl.readChar()\n\t\t}\n\t}\n\treturn tok\n}\n\n// newToken creates a new token with the given type and literal.\nfunc (l *Lexer) newToken(tokenType token.Type, ch byte) token.Token {\n\tliteral := string(ch)\n\treturn token.Token{\n\t\tType:    tokenType,\n\t\tLiteral: literal,\n\t\tLine:    l.line,\n\t\tColumn:  l.column,\n\t}\n}\n\n// readComment reads a comment.\n// // Foo => Token(Foo).\nfunc (l *Lexer) readComment() string {\n\tpos := l.pos + 1\n\tfor {\n\t\tl.readChar()\n\t\tif isNewLine(l.ch) || l.ch == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\t// The current character is a newline.\n\t// skipWhitespace() will handle this for us and increment the line counter.\n\treturn l.input[pos:l.pos]\n}\n\n// readString reads a string from the input.\n// \"Foo\" => Token(Foo).\nfunc (l *Lexer) readString(endChar byte) string {\n\tpos := l.pos + 1\n\tfor {\n\t\tl.readChar()\n\t\tif l.ch == endChar || l.ch == 0 || isNewLine(l.ch) {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn l.input[pos:l.pos]\n}\n\n// readRegex reads a regex pattern from the input, handling escaped delimiters.\n// It counts consecutive backslashes to determine if a delimiter is truly escaped.\n//\n// Examples:\n//\n//\t/foo\\/bar/ => Token(foo\\/bar) - delimiter is escaped\n//\t/foo\\\\/    => Token(foo\\\\)    - delimiter is NOT escaped (backslash is escaped)\n//\t/foo\\\\\\/bar/ => Token(foo\\\\\\/bar) - delimiter is escaped\nfunc (l *Lexer) readRegex(endChar byte) string {\n\tpos := l.pos + 1\n\tfor {\n\t\tl.readChar()\n\t\tif l.ch == 0 || isNewLine(l.ch) {\n\t\t\tbreak\n\t\t}\n\n\t\tif l.ch == '\\\\' {\n\t\t\tbackslashCount := 0\n\n\t\t\tfor l.ch == '\\\\' && l.pos < len(l.input) {\n\t\t\t\tbackslashCount++\n\t\t\t\tl.readChar()\n\t\t\t}\n\n\t\t\tif l.ch == endChar {\n\t\t\t\tif backslashCount%2 == 1 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Note: Even number of backslashes means the delimiter is NOT escaped\n\t\t\t\t// This is the end of the regex\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcontinue\n\t\t}\n\n\t\tif l.ch == endChar {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn l.input[pos:l.pos]\n}\n\n// readJSON reads a JSON object from the input.\n// {\"foo\": \"bar\"} => Token({\"foo\": \"bar\"}).\nfunc (l *Lexer) readJSON() string {\n\tpos := l.pos + 1\n\tfor {\n\t\tl.readChar()\n\t\tif l.ch == '}' || l.ch == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn l.input[pos:l.pos]\n}\n\n// readNumber reads a number from the input.\n// 123 => Token(123).\nfunc (l *Lexer) readNumber() string {\n\tpos := l.pos\n\tfor isDigit(l.ch) || isDot(l.ch) {\n\t\tl.readChar()\n\t}\n\treturn l.input[pos:l.pos]\n}\n\n// readIdentifier reads an identifier from the input.\n// Foo => Token(Foo).\nfunc (l *Lexer) readIdentifier() string {\n\tpos := l.pos\n\tfor isLetter(l.ch) || isDot(l.ch) || isDash(l.ch) || isUnderscore(l.ch) || isSlash(l.ch) || isPercent(l.ch) || isDigit(l.ch) {\n\t\tl.readChar()\n\t}\n\treturn l.input[pos:l.pos]\n}\n\n// skipWhitespace skips whitespace characters.\n// If it encounters a newline, it increments the line counter to keep track\n// of the token's line number.\nfunc (l *Lexer) skipWhitespace() {\n\tfor isWhitespace(l.ch) {\n\t\t// Note: we don't use isNewline since we don't want to double count \\r\\n on\n\t\t// windows and increment the l.line.\n\t\tif l.ch == '\\n' {\n\t\t\tl.line++\n\t\t\tl.column = 0\n\t\t}\n\t\tl.readChar()\n\t}\n}\n\n// isDot returns whether a character is a dot.\nfunc isDot(ch byte) bool {\n\treturn ch == '.'\n}\n\n// isDash returns whether a character is a dash.\nfunc isDash(ch byte) bool {\n\treturn ch == '-'\n}\n\n// isUnderscore returns whether a character is an underscore.\nfunc isUnderscore(ch byte) bool {\n\treturn ch == '_'\n}\n\n// isPercent returns whether a character is a percent.\nfunc isPercent(ch byte) bool {\n\treturn ch == '%'\n}\n\n// isSlash returns whether a character is a slash.\nfunc isSlash(ch byte) bool {\n\treturn ch == '/'\n}\n\n// isLetter returns whether a character is a letter.\nfunc isLetter(ch byte) bool {\n\treturn 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z'\n}\n\n// isDigit returns whether a character is a digit.\nfunc isDigit(ch byte) bool {\n\treturn '0' <= ch && ch <= '9'\n}\n\n// isWhitespace returns whether a character is a whitespace.\nfunc isWhitespace(ch byte) bool {\n\treturn ch == ' ' || ch == '\\t' || ch == '\\n' || ch == '\\r'\n}\n\n// isNewLine returns whether a character is a newline.\n//\n// Note: in windows a single new line is \\r\\n so using isNewline is not\n// recommended for counting the number of new lines.\nfunc isNewLine(ch byte) bool {\n\treturn ch == '\\n' || ch == '\\r'\n}\n\n// peekChar returns the next character in the input without advancing the lexer.\nfunc (l *Lexer) peekChar() byte {\n\tif l.nextPos >= len(l.input) {\n\t\treturn 0\n\t}\n\treturn l.input[l.nextPos]\n}\n"
  },
  {
    "path": "lexer/lexer_test.go",
    "content": "package lexer\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/vhs/token\"\n)\n\nfunc TestNextToken(t *testing.T) {\n\tinput := `\nOutput examples/out.gif\nSet FontSize 42\nSet Padding 5\nSet CursorBlink false\nType \"echo 'Hello, world!'\"\nEnter\nType@.1 \"echo 'Hello, world!'\"\nLeft 3\nSleep 1\nRight@100ms 3\nScrollUp 3\nScrollDown@100ms 2\nSleep 500ms\nCtrl+C\nEnter\nCtrl+@\nCtrl+\\\nAlt+]\nShift+[\nSleep .1\nSleep 100ms\nSleep 2\nWait+Screen@1m /foobar/\nWait+Screen@1m /foo\\/bar/\nWait+Screen@1m /foo\\\\/\nWait+Screen@1m /foo\\\\\\/bar/`\n\n\ttests := []struct {\n\t\texpectedType    token.Type\n\t\texpectedLiteral string\n\t}{\n\t\t{token.OUTPUT, \"Output\"},\n\t\t{token.STRING, \"examples/out.gif\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.FONT_SIZE, \"FontSize\"},\n\t\t{token.NUMBER, \"42\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.PADDING, \"Padding\"},\n\t\t{token.NUMBER, \"5\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.CURSOR_BLINK, \"CursorBlink\"},\n\t\t{token.BOOLEAN, \"false\"},\n\t\t{token.TYPE, \"Type\"},\n\t\t{token.STRING, \"echo 'Hello, world!'\"},\n\t\t{token.ENTER, \"Enter\"},\n\t\t{token.TYPE, \"Type\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \".1\"},\n\t\t{token.STRING, \"echo 'Hello, world!'\"},\n\t\t{token.LEFT, \"Left\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.RIGHT, \"Right\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"100\"},\n\t\t{token.MILLISECONDS, \"ms\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.SCROLL_UP, \"ScrollUp\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.SCROLL_DOWN, \"ScrollDown\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"100\"},\n\t\t{token.MILLISECONDS, \"ms\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \"500\"},\n\t\t{token.MILLISECONDS, \"ms\"},\n\t\t{token.CTRL, \"Ctrl\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"C\"},\n\t\t{token.ENTER, \"Enter\"},\n\t\t{token.CTRL, \"Ctrl\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.CTRL, \"Ctrl\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.BACKSLASH, \"\\\\\"},\n\t\t{token.ALT, \"Alt\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.RIGHT_BRACKET, \"]\"},\n\t\t{token.SHIFT, \"Shift\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.LEFT_BRACKET, \"[\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \".1\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \"100\"},\n\t\t{token.MILLISECONDS, \"ms\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.WAIT, \"Wait\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"Screen\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.MINUTES, \"m\"},\n\t\t{token.REGEX, \"foobar\"},\n\t\t{token.WAIT, \"Wait\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"Screen\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.MINUTES, \"m\"},\n\t\t{token.REGEX, \"foo\\\\/bar\"},\n\t\t{token.WAIT, \"Wait\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"Screen\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.MINUTES, \"m\"},\n\t\t{token.REGEX, \"foo\\\\\\\\\"},\n\t\t{token.WAIT, \"Wait\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"Screen\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.MINUTES, \"m\"},\n\t\t{token.REGEX, \"foo\\\\\\\\\\\\/bar\"},\n\t}\n\n\tl := New(input)\n\n\tfor i, tt := range tests {\n\t\ttok := l.NextToken()\n\n\t\tif tok.Type != tt.expectedType {\n\t\t\tt.Fatalf(\"tests[%d] - tokentype wrong. expected=%q, got=%q\", i, tt.expectedType, tok.Type)\n\t\t}\n\n\t\tif tok.Literal != tt.expectedLiteral {\n\t\t\tt.Fatalf(\"tests[%d] - literal wrong. expected=%q, got=%q\", i, tt.expectedLiteral, tok.Literal)\n\t\t}\n\t}\n}\n\nfunc TestLexTapeFile(t *testing.T) {\n\tinput, err := os.ReadFile(\"../examples/fixtures/all.tape\")\n\tif err != nil {\n\t\tt.Fatal(\"could not read all.tape file\")\n\t}\n\n\ttests := []struct {\n\t\texpectedType    token.Type\n\t\texpectedLiteral string\n\t}{\n\t\t{token.COMMENT, \" All Commands\"},\n\t\t{token.COMMENT, \" Output:\"},\n\t\t{token.OUTPUT, \"Output\"},\n\t\t{token.STRING, \"examples/fixtures/all.gif\"},\n\t\t{token.OUTPUT, \"Output\"},\n\t\t{token.STRING, \"examples/fixtures/all.mp4\"},\n\t\t{token.OUTPUT, \"Output\"},\n\t\t{token.STRING, \"examples/fixtures/all.webm\"},\n\t\t{token.COMMENT, \" Settings:\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.SHELL, \"Shell\"},\n\t\t{token.STRING, \"fish\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.FONT_SIZE, \"FontSize\"},\n\t\t{token.NUMBER, \"22\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.FONT_FAMILY, \"FontFamily\"},\n\t\t{token.STRING, \"DejaVu Sans Mono\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.HEIGHT, \"Height\"},\n\t\t{token.NUMBER, \"600\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.WIDTH, \"Width\"},\n\t\t{token.NUMBER, \"1200\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.LETTER_SPACING, \"LetterSpacing\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.LINE_HEIGHT, \"LineHeight\"},\n\t\t{token.NUMBER, \"1.2\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.THEME, \"Theme\"},\n\t\t{token.JSON, \"{ \\\"name\\\": \\\"Whimsy\\\", \\\"black\\\": \\\"#535178\\\", \\\"red\\\": \\\"#ef6487\\\", \\\"green\\\": \\\"#5eca89\\\", \\\"yellow\\\": \\\"#fdd877\\\", \\\"blue\\\": \\\"#65aef7\\\", \\\"purple\\\": \\\"#aa7ff0\\\", \\\"cyan\\\": \\\"#43c1be\\\", \\\"white\\\": \\\"#ffffff\\\", \\\"brightBlack\\\": \\\"#535178\\\", \\\"brightRed\\\": \\\"#ef6487\\\", \\\"brightGreen\\\": \\\"#5eca89\\\", \\\"brightYellow\\\": \\\"#fdd877\\\", \\\"brightBlue\\\": \\\"#65aef7\\\", \\\"brightPurple\\\": \\\"#aa7ff0\\\", \\\"brightCyan\\\": \\\"#43c1be\\\", \\\"brightWhite\\\": \\\"#ffffff\\\", \\\"background\\\": \\\"#29283b\\\", \\\"foreground\\\": \\\"#b3b0d6\\\", \\\"selectionBackground\\\": \\\"#3d3c58\\\", \\\"cursorColor\\\": \\\"#b3b0d6\\\" }\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.THEME, \"Theme\"},\n\t\t{token.STRING, \"Catppuccin Mocha\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.PADDING, \"Padding\"},\n\t\t{token.NUMBER, \"50\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.FRAMERATE, \"Framerate\"},\n\t\t{token.NUMBER, \"60\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.PLAYBACK_SPEED, \"PlaybackSpeed\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.TYPING_SPEED, \"TypingSpeed\"},\n\t\t{token.NUMBER, \".1\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.LOOP_OFFSET, \"LoopOffset\"},\n\t\t{token.NUMBER, \"60.4\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.LOOP_OFFSET, \"LoopOffset\"},\n\t\t{token.NUMBER, \"20.99\"},\n\t\t{token.PERCENT, \"%\"},\n\t\t{token.SET, \"Set\"},\n\t\t{token.CURSOR_BLINK, \"CursorBlink\"},\n\t\t{token.BOOLEAN, \"false\"},\n\t\t{token.COMMENT, \" Sleep:\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \"500\"},\n\t\t{token.MILLISECONDS, \"ms\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \".5\"},\n\t\t{token.SLEEP, \"Sleep\"},\n\t\t{token.NUMBER, \"0.5\"},\n\t\t{token.COMMENT, \" Type:\"},\n\t\t{token.TYPE, \"Type\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \".5\"},\n\t\t{token.STRING, \"All\"},\n\t\t{token.TYPE, \"Type\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"500\"},\n\t\t{token.MILLISECONDS, \"ms\"},\n\t\t{token.STRING, \"All\"},\n\t\t{token.TYPE, \"Type\"},\n\t\t{token.STRING, \"Double Quote\"},\n\t\t{token.TYPE, \"Type\"},\n\t\t{token.STRING, \"\\\"Single\\\" Quote\"},\n\t\t{token.TYPE, \"Type\"},\n\t\t{token.STRING, `\"Backtick\" 'Quote'`},\n\t\t{token.COMMENT, \" Keys:\"},\n\t\t{token.BACKSPACE, \"Backspace\"},\n\t\t{token.BACKSPACE, \"Backspace\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.BACKSPACE, \"Backspace\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.DELETE, \"Delete\"},\n\t\t{token.DELETE, \"Delete\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.DELETE, \"Delete\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.INSERT, \"Insert\"},\n\t\t{token.INSERT, \"Insert\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.INSERT, \"Insert\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.DOWN, \"Down\"},\n\t\t{token.DOWN, \"Down\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.DOWN, \"Down\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.PAGE_DOWN, \"PageDown\"},\n\t\t{token.PAGE_DOWN, \"PageDown\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.PAGE_DOWN, \"PageDown\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.SCROLL_DOWN, \"ScrollDown\"},\n\t\t{token.SCROLL_DOWN, \"ScrollDown\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.SCROLL_DOWN, \"ScrollDown\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.ENTER, \"Enter\"},\n\t\t{token.ENTER, \"Enter\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.ENTER, \"Enter\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.SPACE, \"Space\"},\n\t\t{token.SPACE, \"Space\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.SPACE, \"Space\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.TAB, \"Tab\"},\n\t\t{token.TAB, \"Tab\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.TAB, \"Tab\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.LEFT, \"Left\"},\n\t\t{token.LEFT, \"Left\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.LEFT, \"Left\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.RIGHT, \"Right\"},\n\t\t{token.RIGHT, \"Right\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.RIGHT, \"Right\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.UP, \"Up\"},\n\t\t{token.UP, \"Up\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.UP, \"Up\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.PAGE_UP, \"PageUp\"},\n\t\t{token.PAGE_UP, \"PageUp\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.PAGE_UP, \"PageUp\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.SCROLL_UP, \"ScrollUp\"},\n\t\t{token.SCROLL_UP, \"ScrollUp\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.SCROLL_UP, \"ScrollUp\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.DOWN, \"Down\"},\n\t\t{token.DOWN, \"Down\"},\n\t\t{token.NUMBER, \"2\"},\n\t\t{token.DOWN, \"Down\"},\n\t\t{token.AT, \"@\"},\n\t\t{token.NUMBER, \"1\"},\n\t\t{token.NUMBER, \"3\"},\n\t\t{token.COMMENT, \" Control:\"},\n\t\t{token.CTRL, \"Ctrl\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"C\"},\n\t\t{token.CTRL, \"Ctrl\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"L\"},\n\t\t{token.CTRL, \"Ctrl\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"R\"},\n\t\t{token.COMMENT, \" Alt:\"},\n\t\t{token.ALT, \"Alt\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \".\"},\n\t\t{token.ALT, \"Alt\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"L\"},\n\t\t{token.ALT, \"Alt\"},\n\t\t{token.PLUS, \"+\"},\n\t\t{token.STRING, \"i\"},\n\t\t{token.COMMENT, \" Display:\"},\n\t\t{token.HIDE, \"Hide\"},\n\t\t{token.SHOW, \"Show\"},\n\t}\n\n\tl := New(string(input))\n\n\tfor i, tt := range tests {\n\t\ttok := l.NextToken()\n\n\t\tif tok.Type != tt.expectedType {\n\t\t\tt.Fatalf(\"tests[%d] - tokentype wrong. expected=%q, got=%q\", i, tt.expectedType, tok.Type)\n\t\t}\n\n\t\tif tok.Literal != tt.expectedLiteral {\n\t\t\tt.Fatalf(\"tests[%d] - literal wrong. expected=%q, got=%q\", i, tt.expectedLiteral, tok.Literal)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "main.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t_ \"embed\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t\"syscall\"\n\n\t\"github.com/charmbracelet/vhs/lexer\"\n\t\"github.com/charmbracelet/vhs/parser\"\n\tversion \"github.com/hashicorp/go-version\"\n\t\"github.com/mattn/go-isatty\"\n\t\"github.com/spf13/cobra\"\n)\n\nconst extension = \".tape\"\n\nvar (\n\t// Version stores the build version of VHS at the time of packaging through -ldflags.\n\tVersion string\n\n\t// CommitSHA stores the commit SHA of VHS at the time of packaging through -ldflags.\n\tCommitSHA string\n\n\tttydMinVersion = version.Must(version.NewVersion(\"1.7.2\"))\n\n\tpublishFlag bool\n\toutputs     *[]string\n\n\tquietFlag bool\n\n\t//nolint:wrapcheck\n\trootCmd = &cobra.Command{\n\t\tUse:           \"vhs <file>\",\n\t\tShort:         \"Run a given tape file and generates its outputs.\",\n\t\tArgs:          cobra.MaximumNArgs(1),\n\t\tSilenceUsage:  true,\n\t\tSilenceErrors: true, // we print our own errors\n\t\tPersistentPreRun: func(_ *cobra.Command, _ []string) {\n\t\t\tlog.SetFlags(0)\n\t\t\tif quietFlag {\n\t\t\t\tlog.SetOutput(io.Discard)\n\t\t\t}\n\t\t},\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\terr := ensureDependencies()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tin := cmd.InOrStdin()\n\t\t\t// Set the input to the file contents if a file is given\n\t\t\t// otherwise, use stdin\n\t\t\tif len(args) > 0 && args[0] != \"-\" {\n\t\t\t\tin, err = os.Open(args[0])\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tlog.Println(GrayStyle.Render(\"File: \" + args[0]))\n\t\t\t} else {\n\t\t\t\tstat, _ := os.Stdin.Stat()\n\t\t\t\tif (stat.Mode() & os.ModeCharDevice) != 0 {\n\t\t\t\t\t// The user ran vhs without any arguments or stdin.\n\t\t\t\t\t// Print the usage.\n\t\t\t\t\treturn cmd.Help()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tinput, err := io.ReadAll(in)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif string(input) == \"\" {\n\t\t\t\treturn errors.New(\"no input provided\")\n\t\t\t}\n\n\t\t\tvar publishFile string\n\t\t\tout := cmd.OutOrStdout()\n\t\t\tif quietFlag {\n\t\t\t\tout = io.Discard\n\t\t\t}\n\t\t\terrs := Evaluate(cmd.Context(), string(input), out, func(v *VHS) {\n\t\t\t\t// Output is being overridden, prevent all outputs\n\t\t\t\tif len(*outputs) <= 0 {\n\t\t\t\t\tpublishFile = v.Options.Video.Output.GIF\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tfor _, output := range *outputs {\n\t\t\t\t\tif strings.HasSuffix(output, gif) {\n\t\t\t\t\t\tv.Options.Video.Output.GIF = output\n\t\t\t\t\t} else if strings.HasSuffix(output, webm) {\n\t\t\t\t\t\tv.Options.Video.Output.WebM = output\n\t\t\t\t\t} else if strings.HasSuffix(output, mp4) {\n\t\t\t\t\t\tv.Options.Video.Output.MP4 = output\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpublishFile = v.Options.Video.Output.GIF\n\t\t\t})\n\n\t\t\tpublishEnv, publishEnvSet := os.LookupEnv(\"VHS_PUBLISH\")\n\t\t\tif !publishEnvSet && !publishFlag && len(errs) == 0 {\n\t\t\t\tlog.Println(FaintStyle.Render(\"Host your GIF on vhs.charm.sh: vhs publish <file>.gif\"))\n\t\t\t}\n\n\t\t\tif len(errs) > 0 {\n\t\t\t\tprintErrors(os.Stderr, string(input), errs)\n\t\t\t\treturn errors.New(\"recording failed\")\n\t\t\t}\n\n\t\t\tif (publishFlag || publishEnv == \"true\") && publishFile != \"\" {\n\t\t\t\tif isatty.IsTerminal(os.Stdout.Fd()) {\n\t\t\t\t\tlog.Printf(GrayStyle.Render(\"Publishing %s... \"), publishFile)\n\t\t\t\t}\n\n\t\t\t\turl, err := Publish(cmd.Context(), publishFile)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif quietFlag {\n\t\t\t\t\tcmd.Println(url)\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tif isatty.IsTerminal(os.Stdout.Fd()) {\n\t\t\t\t\tlog.Println(StringStyle.Render(\"Done!\"))\n\t\t\t\t\tpublishShareInstructions(url)\n\t\t\t\t}\n\t\t\t\tlog.Println(\"  \" + URLStyle.Render(url))\n\t\t\t\tif isatty.IsTerminal(os.Stdout.Fd()) {\n\t\t\t\t\tlog.Println()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tmarkdown  bool\n\tthemesCmd = &cobra.Command{\n\t\tUse:   \"themes\",\n\t\tShort: \"List all the available themes, one per line\",\n\t\tArgs:  cobra.NoArgs,\n\t\tRunE: func(_ *cobra.Command, _ []string) error {\n\t\t\tvar prefix, suffix string\n\t\t\tif markdown {\n\t\t\t\tlog.Printf(\"# Themes\\n\\n\")\n\t\t\t\tprefix, suffix = \"* `\", \"`\"\n\t\t\t}\n\t\t\tthemes, err := sortedThemeNames()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfor _, theme := range themes {\n\t\t\t\tlog.Printf(\"%s%s%s\\n\", prefix, theme, suffix)\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tshell     string\n\trecordCmd = &cobra.Command{\n\t\tUse:   \"record\",\n\t\tShort: \"Create a new tape file by recording your actions\",\n\t\tArgs:  cobra.NoArgs,\n\t\tRunE:  Record,\n\t}\n\n\t//nolint:wrapcheck\n\tnewCmd = &cobra.Command{\n\t\tUse:   \"new <name>\",\n\t\tShort: \"Create a new tape file with example tape file contents and documentation\",\n\t\tArgs:  cobra.ExactArgs(1),\n\t\tRunE: func(_ *cobra.Command, args []string) error {\n\t\t\tname := strings.TrimSuffix(args[0], extension)\n\t\t\tfileName := name + extension\n\n\t\t\tf, err := os.Create(fileName)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t_, err = f.Write(bytes.Replace(demoTape, []byte(\"examples/demo.gif\"), []byte(name+\".gif\"), 1))\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tlog.Println(\"Created \" + fileName)\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tvalidateCmd = &cobra.Command{\n\t\tUse:   \"validate <file>...\",\n\t\tShort: \"Validate a glob file path and parses all the files to ensure they are valid without running them.\",\n\t\tArgs:  cobra.MinimumNArgs(1),\n\t\tRunE: func(_ *cobra.Command, args []string) error {\n\t\t\tvalid := true\n\n\t\t\tfor _, file := range args {\n\t\t\t\tb, err := os.ReadFile(file)\n\t\t\t\tif err != nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tl := lexer.New(string(b))\n\t\t\t\tp := parser.New(l)\n\n\t\t\t\t_ = p.Parse()\n\t\t\t\terrs := p.Errors()\n\n\t\t\t\tif len(errs) != 0 {\n\t\t\t\t\tlog.Println(ErrorFileStyle.Render(file))\n\n\t\t\t\t\tfor _, err := range errs {\n\t\t\t\t\t\tprintError(os.Stderr, string(b), err)\n\t\t\t\t\t}\n\t\t\t\t\tvalid = false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif !valid {\n\t\t\t\treturn errors.New(\"invalid tape file(s)\")\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n)\n\nfunc main() {\n\tctx, cancel := signal.NotifyContext(\n\t\tcontext.Background(),\n\t\tos.Interrupt, syscall.SIGTERM,\n\t)\n\tdefer cancel()\n\n\tif err := rootCmd.ExecuteContext(ctx); err != nil {\n\t\tfmt.Println(err)\n\t\tos.Exit(1)\n\t}\n}\n\nfunc init() {\n\trootCmd.Flags().BoolVarP(&publishFlag, \"publish\", \"p\", false, \"publish your GIF to vhs.charm.sh and get a shareable URL\")\n\trootCmd.PersistentFlags().BoolVarP(&quietFlag, \"quiet\", \"q\", false, \"quiet do not log messages. If publish flag is provided, it will log shareable URL\")\n\n\toutputs = rootCmd.Flags().StringSliceP(\"output\", \"o\", []string{}, \"file name(s) of video output\")\n\tthemesCmd.Flags().BoolVar(&markdown, \"markdown\", false, \"output as markdown\")\n\t_ = themesCmd.Flags().MarkHidden(\"markdown\")\n\trecordShell := filepath.Base(os.Getenv(\"SHELL\"))\n\tif recordShell == \"\" {\n\t\trecordShell = defaultShell\n\t}\n\trecordCmd.Flags().StringVarP(&shell, \"shell\", \"s\", recordShell, \"shell for recording\")\n\trootCmd.AddCommand(\n\t\trecordCmd,\n\t\tnewCmd,\n\t\tthemesCmd,\n\t\tvalidateCmd,\n\t\tmanCmd,\n\t\tserveCmd,\n\t\tpublishCmd,\n\t)\n\trootCmd.CompletionOptions.HiddenDefaultCmd = true\n\n\tif len(CommitSHA) >= 7 { //nolint:mnd\n\t\tvt := rootCmd.VersionTemplate()\n\t\trootCmd.SetVersionTemplate(vt[:len(vt)-1] + \" (\" + CommitSHA[0:7] + \")\\n\")\n\t}\n\tif Version == \"\" {\n\t\tif info, ok := debug.ReadBuildInfo(); ok && info.Main.Sum != \"\" {\n\t\t\tVersion = info.Main.Version\n\t\t} else {\n\t\t\tVersion = \"unknown (built from source)\"\n\t\t}\n\t}\n\trootCmd.Version = Version\n}\n\nvar versionRegex = regexp.MustCompile(`\\d+\\.\\d+\\.\\d+`)\n\n// getVersion returns the parsed version of a program.\nfunc getVersion(program string) *version.Version {\n\tcmd := exec.Command(program, \"--version\")\n\tout, err := cmd.Output()\n\tif err != nil {\n\t\treturn nil\n\t}\n\tprogramVersion, _ := version.NewVersion(versionRegex.FindString(string(out)))\n\treturn programVersion\n}\n\n// ensureDependencies ensures that all dependencies are correctly installed\n// and versioned before continuing.\nfunc ensureDependencies() error {\n\t_, ffmpegErr := exec.LookPath(\"ffmpeg\")\n\tif ffmpegErr != nil {\n\t\treturn fmt.Errorf(\"ffmpeg is not installed. Install it from: http://ffmpeg.org\")\n\t}\n\t_, ttydErr := exec.LookPath(\"ttyd\")\n\tif ttydErr != nil {\n\t\treturn fmt.Errorf(\"ttyd is not installed. Install it from: https://github.com/tsl0922/ttyd\")\n\t}\n\t_, shellErr := exec.LookPath(defaultShell)\n\tif shellErr != nil {\n\t\treturn fmt.Errorf(\"%v is not installed\", defaultShell)\n\t}\n\n\tttydVersion := getVersion(\"ttyd\")\n\tif ttydVersion == nil || ttydVersion.LessThan(ttydMinVersion) {\n\t\treturn fmt.Errorf(\"ttyd version (%s) is out of date, VHS requires %s\\n%s\",\n\t\t\tttydVersion,\n\t\t\tttydMinVersion,\n\t\t\t\"Install the latest version from: https://github.com/tsl0922/ttyd\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "man.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/glamour\"\n\t\"github.com/mattn/go-isatty\"\n\tmcobra \"github.com/muesli/mango-cobra\"\n\t\"github.com/muesli/roff\"\n\t\"github.com/spf13/cobra\"\n)\n\n// We use this special character to represent the character that delimits the\n// important symbols in the text. We replace these to code in markdown and bold\n// in roff.\nconst specialChar = \"%\"\n\nvar (\n\tmanDescription = `VHS lets you write terminal GIFs as code.\nVHS reads .tape files and renders GIFs (videos).\nA tape file is a script made up of commands describing what actions to perform in the render.\n\nThe following is a list of all possible commands in VHS:\n\n* %Output% <path>.(gif|webm|mp4)\n* %Require% <program>\n* %Set% <setting> <value>\n* %Sleep% <time>\n* %Type% \"<string>\"\n* %Ctrl% [+Alt][+Shift]+<char>\n* %Backspace% [repeat]\n* %Delete% [repeat]\n* %Insert% [repeat]\n* %Down% [repeat]\n* %Enter% [repeat]\n* %Left% [repeat]\n* %Right% [repeat]\n* %Tab% [repeat]\n* %Up% [repeat]\n* %PageUp% [repeat]\n* %PageDown% [repeat]\n* %ScrollUp% [repeat]\n* %ScrollDown% [repeat]\n* %Hide%\n* %Show%\n* %Wait%[+Screen][@<timeout>] /<regexp>/\n* %Escape%\n* %Alt%+<key>\n* %Space% [repeat]\n* %Source% <path>.tape\n* %Screenshot% <path>.png\n* %Copy% \"<string>\"\n* %Paste%\n`\n\n\tmanOutput = `The Output command instructs VHS where to save the output of the recording.\nFile names with the extension %.gif%, %.webm%, %.mp4% will have the respective file types.\n`\n\n\tmanSettings = `The Set command allows VHS to adjust settings in the terminal, such as fonts, dimensions, and themes.\n\nThe following is a list of all possible setting commands in VHS:\n\n* Set %Shell% <string>\n* Set %FontSize% <number>\n* Set %FontFamily% <string>\n* Set %Height% <number>\n* Set %Width% <number>\n* Set %LetterSpacing% <float>\n* Set %LineHeight% <float>\n* Set %TypingSpeed% <time>\n* Set %Theme% <json|string>\n* Set %Padding% <number>\n* Set %Framerate% <number>\n* Set %PlaybackSpeed% <float>\n* Set %WaitTimeout% <time>\n* Set %WaitPattern% <regexp>\n`\n\tmanBugs = \"See GitHub Issues: <https://github.com/charmbracelet/vhs/issues>\"\n\n\tmanAuthor = \"Charm <vt100@charm.sh>\"\n)\n\n//nolint:wrapcheck\nvar manCmd = &cobra.Command{\n\tUse:     \"manual\",\n\tAliases: []string{\"man\"},\n\tShort:   \"Generate man pages\",\n\tArgs:    cobra.NoArgs,\n\tHidden:  true,\n\tRunE: func(_ *cobra.Command, _ []string) error {\n\t\tif isatty.IsTerminal(os.Stdout.Fd()) {\n\t\t\trenderer, err := glamour.NewTermRenderer(\n\t\t\t\tglamour.WithStyles(GlamourTheme),\n\t\t\t)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tv, err := renderer.Render(markdownManual())\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfmt.Println(v)\n\t\t\treturn nil\n\t\t}\n\n\t\tmanPage, err := mcobra.NewManPage(1, rootCmd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tmanPage = manPage.\n\t\t\tWithLongDescription(sanitizeSpecial(manDescription)).\n\t\t\tWithSection(\"Output\", sanitizeSpecial(manOutput)).\n\t\t\tWithSection(\"Settings\", sanitizeSpecial(manSettings)).\n\t\t\tWithSection(\"Bugs\", sanitizeSpecial(manBugs)).\n\t\t\tWithSection(\"Author\", sanitizeSpecial(manAuthor)).\n\t\t\tWithSection(\"Copyright\", \"(C) 2021-2022 Charmbracelet, Inc.\\n\"+\n\t\t\t\t\"Released under MIT license.\")\n\n\t\tfmt.Println(manPage.Build(roff.NewDocument()))\n\t\treturn nil\n\t},\n}\n\nfunc markdownManual() string {\n\treturn fmt.Sprint(\n\t\t\"# MANUAL\\n\", sanitizeMarkdown(manDescription),\n\t\t\"# OUTPUT\\n\", sanitizeMarkdown(manOutput),\n\t\t\"# SETTING\\n\", sanitizeMarkdown(manSettings),\n\t\t\"# BUGS\\n\", manBugs,\n\t\t\"\\n# AUTHOR\\n\", manAuthor,\n\t)\n}\n\nfunc sanitizeMarkdown(s string) string {\n\treturn strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(\n\t\ts, \"<\", \"&lt;\"), \">\", \"&gt;\"), specialChar, \"`\")\n}\n\nfunc sanitizeSpecial(s string) string {\n\treturn strings.ReplaceAll(s, specialChar, \"\")\n}\n"
  },
  {
    "path": "parser/parser.go",
    "content": "// Package parser provides a parser for the VHS Tape language.\npackage parser\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/vhs/lexer\"\n\t\"github.com/charmbracelet/vhs/token\"\n)\n\n// NewError returns a new parser.Error with the given token and message.\nfunc NewError(token token.Token, msg string) Error {\n\treturn Error{\n\t\tToken: token,\n\t\tMsg:   msg,\n\t}\n}\n\n// CommandType is a type that represents a command.\ntype CommandType token.Type\n\n// CommandTypes is a list of the available commands that can be executed.\nvar CommandTypes = []CommandType{\n\ttoken.BACKSPACE,\n\ttoken.DELETE,\n\ttoken.INSERT,\n\ttoken.CTRL,\n\ttoken.ALT,\n\ttoken.DOWN,\n\ttoken.ENTER,\n\ttoken.ESCAPE,\n\ttoken.ILLEGAL,\n\ttoken.LEFT,\n\ttoken.PAGE_UP,\n\ttoken.PAGE_DOWN,\n\ttoken.SCROLL_UP,\n\ttoken.SCROLL_DOWN,\n\ttoken.RIGHT,\n\ttoken.SET,\n\ttoken.OUTPUT,\n\ttoken.SLEEP,\n\ttoken.SPACE,\n\ttoken.HIDE,\n\ttoken.REQUIRE,\n\ttoken.SHOW,\n\ttoken.TAB,\n\ttoken.TYPE,\n\ttoken.UP,\n\ttoken.WAIT,\n\ttoken.SOURCE,\n\ttoken.SCREENSHOT,\n\ttoken.COPY,\n\ttoken.PASTE,\n\ttoken.ENV,\n}\n\n// String returns the string representation of the command.\nfunc (c CommandType) String() string { return token.ToCamel(string(c)) }\n\n// Command represents a command with options and arguments.\ntype Command struct {\n\tType    CommandType\n\tOptions string\n\tArgs    string\n\tSource  string\n}\n\n// String returns the string representation of the command.\n// This includes the options and arguments of the command.\nfunc (c Command) String() string {\n\tif c.Options != \"\" {\n\t\treturn fmt.Sprintf(\"%s %s %s\", c.Type, c.Options, c.Args)\n\t}\n\treturn fmt.Sprintf(\"%s %s\", c.Type, c.Options)\n}\n\n// Error represents an error with parsing a tape file.\n// It tracks the token causing the error and a human readable error message.\ntype Error struct {\n\tToken token.Token\n\tMsg   string\n}\n\n// String returns a human readable error message printing the token line number\n// and message.\nfunc (e Error) String() string {\n\treturn fmt.Sprintf(\"%2d:%-2d │ %s\", e.Token.Line, e.Token.Column, e.Msg)\n}\n\n// Error implements the error interface.\nfunc (e Error) Error() string {\n\treturn e.String()\n}\n\n// Parser is the structure that manages the parsing of tokens.\ntype Parser struct {\n\tl      *lexer.Lexer\n\terrors []Error\n\tcur    token.Token\n\tpeek   token.Token\n}\n\n// New returns a new Parser.\nfunc New(l *lexer.Lexer) *Parser {\n\tp := &Parser{l: l, errors: []Error{}}\n\n\t// Read two tokens, so cur and peek are both set.\n\tp.nextToken()\n\tp.nextToken()\n\n\treturn p\n}\n\n// Parse takes an input string provided by the lexer and parses it into a\n// list of commands.\nfunc (p *Parser) Parse() []Command {\n\tcmds := []Command{}\n\n\tfor p.cur.Type != token.EOF {\n\t\tif p.cur.Type == token.COMMENT {\n\t\t\tp.nextToken()\n\t\t\tcontinue\n\t\t}\n\t\tcmds = append(cmds, p.parseCommand()...)\n\t\tp.nextToken()\n\t}\n\n\treturn cmds\n}\n\n// parseCommand parses a command.\nfunc (p *Parser) parseCommand() []Command {\n\tswitch p.cur.Type {\n\tcase token.SPACE,\n\t\ttoken.BACKSPACE,\n\t\ttoken.DELETE,\n\t\ttoken.INSERT,\n\t\ttoken.ENTER,\n\t\ttoken.ESCAPE,\n\t\ttoken.TAB,\n\t\ttoken.DOWN,\n\t\ttoken.LEFT,\n\t\ttoken.RIGHT,\n\t\ttoken.UP,\n\t\ttoken.PAGE_UP,\n\t\ttoken.PAGE_DOWN,\n\t\ttoken.SCROLL_UP,\n\t\ttoken.SCROLL_DOWN:\n\t\treturn []Command{p.parseKeypress(p.cur.Type)}\n\tcase token.SET:\n\t\treturn []Command{p.parseSet()}\n\tcase token.OUTPUT:\n\t\treturn []Command{p.parseOutput()}\n\tcase token.SLEEP:\n\t\treturn []Command{p.parseSleep()}\n\tcase token.TYPE:\n\t\treturn []Command{p.parseType()}\n\tcase token.CTRL:\n\t\treturn []Command{p.parseCtrl()}\n\tcase token.ALT:\n\t\treturn []Command{p.parseAlt()}\n\tcase token.SHIFT:\n\t\treturn []Command{p.parseShift()}\n\tcase token.HIDE:\n\t\treturn []Command{p.parseHide()}\n\tcase token.REQUIRE:\n\t\treturn []Command{p.parseRequire()}\n\tcase token.SHOW:\n\t\treturn []Command{p.parseShow()}\n\tcase token.WAIT:\n\t\treturn []Command{p.parseWait()}\n\tcase token.SOURCE:\n\t\treturn p.parseSource()\n\tcase token.SCREENSHOT:\n\t\treturn []Command{p.parseScreenshot()}\n\tcase token.COPY:\n\t\treturn []Command{p.parseCopy()}\n\tcase token.PASTE:\n\t\treturn []Command{p.parsePaste()}\n\tcase token.ENV:\n\t\treturn []Command{p.parseEnv()}\n\tdefault:\n\t\tp.errors = append(p.errors, NewError(p.cur, \"Invalid command: \"+p.cur.Literal))\n\t\treturn []Command{{Type: token.ILLEGAL}}\n\t}\n}\n\nfunc (p *Parser) parseWait() Command {\n\tcmd := Command{Type: token.WAIT}\n\n\tif p.peek.Type == token.PLUS {\n\t\tp.nextToken()\n\t\tif p.peek.Type != token.STRING || (p.peek.Literal != \"Line\" && p.peek.Literal != \"Screen\") {\n\t\t\tp.errors = append(p.errors, NewError(p.peek, \"Wait+ expects Line or Screen\"))\n\t\t\treturn cmd\n\t\t}\n\t\tcmd.Args = p.peek.Literal\n\t\tp.nextToken()\n\t} else {\n\t\tcmd.Args = \"Line\"\n\t}\n\n\tcmd.Options = p.parseSpeed()\n\tif cmd.Options != \"\" {\n\t\tdur, _ := time.ParseDuration(cmd.Options)\n\t\tif dur <= 0 {\n\t\t\tp.errors = append(p.errors, NewError(p.peek, \"Wait expects positive duration\"))\n\t\t\treturn cmd\n\t\t}\n\t}\n\n\tif p.peek.Type != token.REGEX {\n\t\t// fallback to default\n\t\treturn cmd\n\t}\n\tp.nextToken()\n\tif _, err := regexp.Compile(p.cur.Literal); err != nil {\n\t\tp.errors = append(p.errors, NewError(p.cur, fmt.Sprintf(\"Invalid regular expression '%s': %v\", p.cur.Literal, err)))\n\t\treturn cmd\n\t}\n\n\tcmd.Args += \" \" + p.cur.Literal\n\n\treturn cmd\n}\n\n// parseSpeed parses a typing speed indication.\n//\n// i.e. @<time>\n//\n// This is optional (defaults to 100ms), thus skips (rather than error-ing)\n// if the typing speed is not specified.\nfunc (p *Parser) parseSpeed() string {\n\tif p.peek.Type == token.AT {\n\t\tp.nextToken()\n\t\treturn p.parseTime()\n\t}\n\treturn \"\"\n}\n\n// parseRepeat parses an optional repeat count for a command.\n//\n// i.e. Backspace [count]\n//\n// This is optional (defaults to 1), thus skips (rather than error-ing)\n// if the repeat count is not specified.\nfunc (p *Parser) parseRepeat() string {\n\tif p.peek.Type == token.NUMBER {\n\t\tcount := p.peek.Literal\n\t\tp.nextToken()\n\t\treturn count\n\t}\n\n\treturn \"1\"\n}\n\n// parseTime parses a time argument.\n//\n//\t<number>[ms]\nfunc (p *Parser) parseTime() string {\n\tvar t string\n\n\tif p.peek.Type == token.NUMBER {\n\t\tt = p.peek.Literal\n\t\tp.nextToken()\n\t} else {\n\t\tp.errors = append(p.errors, NewError(p.cur, \"Expected time after \"+p.cur.Literal))\n\t\treturn \"\"\n\t}\n\n\t// Allow TypingSpeed to have bare units (e.g. 50ms, 100ms)\n\tif p.peek.Type == token.MILLISECONDS || p.peek.Type == token.SECONDS || p.peek.Type == token.MINUTES {\n\t\tt += p.peek.Literal\n\t\tp.nextToken()\n\t} else {\n\t\tt += \"s\"\n\t}\n\n\treturn t\n}\n\n// parseCtrl parses a control command.\n// A control command takes one or multiples characters and/or modifiers to type while ctrl is held down.\n//\n//\tCtrl[+Alt][+Shift]+<char>\n//\tE.g:\n//\tCtrl+Shift+O\n//\tCtrl+Alt+Shift+P\nfunc (p *Parser) parseCtrl() Command {\n\tvar args []string\n\n\tinModifierChain := true\n\tfor p.peek.Type == token.PLUS {\n\t\tp.nextToken()\n\t\tpeek := p.peek\n\n\t\t// Get key from keywords and check if it's a valid modifier\n\t\tif k := token.Keywords[peek.Literal]; token.IsModifier(k) {\n\t\t\tif !inModifierChain {\n\t\t\t\tp.errors = append(p.errors, NewError(p.cur, \"Modifiers must come before other characters\"))\n\t\t\t\t// Clear args so the error is returned\n\t\t\t\targs = nil\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\targs = append(args, peek.Literal)\n\t\t\tp.nextToken()\n\t\t\tcontinue\n\t\t}\n\n\t\tinModifierChain = false\n\n\t\t// Add key argument.\n\t\tswitch {\n\t\tcase peek.Type == token.ENTER,\n\t\t\tpeek.Type == token.SPACE,\n\t\t\tpeek.Type == token.BACKSPACE,\n\t\t\tpeek.Type == token.MINUS,\n\t\t\tpeek.Type == token.AT,\n\t\t\tpeek.Type == token.LEFT_BRACKET,\n\t\t\tpeek.Type == token.RIGHT_BRACKET,\n\t\t\tpeek.Type == token.CARET,\n\t\t\tpeek.Type == token.BACKSLASH,\n\t\t\tpeek.Type == token.LEFT,\n\t\t\tpeek.Type == token.RIGHT,\n\t\t\tpeek.Type == token.UP,\n\t\t\tpeek.Type == token.DOWN,\n\t\t\tpeek.Type == token.STRING && len(peek.Literal) == 1:\n\t\t\targs = append(args, peek.Literal)\n\t\tdefault:\n\t\t\t// Key arguments with len > 1 are not valid\n\t\t\tp.errors = append(p.errors,\n\t\t\t\tNewError(p.cur, \"Not a valid modifier\"),\n\t\t\t\tNewError(p.cur, \"Invalid control argument: \"+p.cur.Literal))\n\t\t}\n\n\t\tp.nextToken()\n\t}\n\n\tif len(args) == 0 {\n\t\tp.errors = append(p.errors, NewError(p.cur, \"Expected control character with args, got \"+p.cur.Literal))\n\t}\n\n\tctrlArgs := strings.Join(args, \" \")\n\treturn Command{Type: token.CTRL, Args: ctrlArgs}\n}\n\n// parseAlt parses an alt command.\n// An alt command takes a character to type while the modifier is held down.\n//\n//\tAlt+<character>\nfunc (p *Parser) parseAlt() Command {\n\tif p.peek.Type == token.PLUS {\n\t\tp.nextToken()\n\t\tif p.peek.Type == token.STRING ||\n\t\t\tp.peek.Type == token.ENTER ||\n\t\t\tp.peek.Type == token.LEFT_BRACKET ||\n\t\t\tp.peek.Type == token.RIGHT_BRACKET ||\n\t\t\tp.peek.Type == token.TAB {\n\t\t\tc := p.peek.Literal\n\t\t\tp.nextToken()\n\t\t\treturn Command{Type: token.ALT, Args: c}\n\t\t}\n\t}\n\n\tp.errors = append(p.errors, NewError(p.cur, \"Expected alt character, got \"+p.cur.Literal))\n\treturn Command{Type: token.ALT}\n}\n\n// parseShift parses a shift command.\n// A shift command takes one character and types while shift is held down.\n//\n//\tShift+<char>\n//\tE.g.\n//\tShift+A\n//\tShift+Tab\n//\tShift+Enter\nfunc (p *Parser) parseShift() Command {\n\tif p.peek.Type == token.PLUS {\n\t\tp.nextToken()\n\t\tif p.peek.Type == token.STRING ||\n\t\t\tp.peek.Type == token.ENTER ||\n\t\t\tp.peek.Type == token.LEFT_BRACKET ||\n\t\t\tp.peek.Type == token.RIGHT_BRACKET ||\n\t\t\tp.peek.Type == token.TAB {\n\t\t\tc := p.peek.Literal\n\t\t\tp.nextToken()\n\t\t\treturn Command{Type: token.SHIFT, Args: c}\n\t\t}\n\t}\n\n\tp.errors = append(p.errors, NewError(p.cur, \"Expected shift character, got \"+p.cur.Literal))\n\treturn Command{Type: token.SHIFT}\n}\n\n// parseKeypress parses a repeatable and time adjustable keypress command.\n// A keypress command takes an optional typing speed and optional count.\n//\n//\tKey[@<time>] [count]\nfunc (p *Parser) parseKeypress(ct token.Type) Command {\n\tcmd := Command{Type: CommandType(ct)}\n\tcmd.Options = p.parseSpeed()\n\tcmd.Args = p.parseRepeat()\n\treturn cmd\n}\n\n// parseOutput parses an output command.\n// An output command takes a file path to which to output.\n//\n//\tOutput <path>\nfunc (p *Parser) parseOutput() Command {\n\tcmd := Command{Type: token.OUTPUT}\n\n\tif p.peek.Type != token.STRING {\n\t\tp.errors = append(p.errors, NewError(p.cur, \"Expected file path after output\"))\n\t\treturn cmd\n\t}\n\n\text := filepath.Ext(p.peek.Literal)\n\tif ext != \"\" {\n\t\tcmd.Options = ext\n\t} else {\n\t\tcmd.Options = \".png\"\n\t\tif !strings.HasSuffix(p.peek.Literal, \"/\") {\n\t\t\tp.errors = append(p.errors, NewError(p.peek, \"Expected folder with trailing slash\"))\n\t\t}\n\t}\n\n\tcmd.Args = p.peek.Literal\n\tp.nextToken()\n\treturn cmd\n}\n\n// parseSet parses a set command.\n// A set command takes a setting name and a value.\n//\n//\tSet <setting> <value>\nfunc (p *Parser) parseSet() Command {\n\tcmd := Command{Type: token.SET}\n\n\tif token.IsSetting(p.peek.Type) {\n\t\tcmd.Options = p.peek.Literal\n\t} else {\n\t\tp.errors = append(p.errors, NewError(p.peek, \"Unknown setting: \"+p.peek.Literal))\n\t}\n\tp.nextToken()\n\n\tswitch p.cur.Type {\n\tcase token.WAIT_TIMEOUT:\n\t\tcmd.Args = p.parseTime()\n\tcase token.WAIT_PATTERN:\n\t\tcmd.Args = p.peek.Literal\n\t\t_, err := regexp.Compile(p.peek.Literal)\n\t\tif err != nil {\n\t\t\tp.errors = append(p.errors, NewError(p.peek, \"Invalid regexp pattern: \"+p.peek.Literal))\n\t\t}\n\t\tp.nextToken()\n\tcase token.LOOP_OFFSET:\n\t\tcmd.Args = p.peek.Literal\n\t\tp.nextToken()\n\t\t// Allow LoopOffset without '%'\n\t\t// Set LoopOffset 20\n\t\tcmd.Args += \"%\"\n\t\tif p.peek.Type == token.PERCENT {\n\t\t\tp.nextToken()\n\t\t}\n\tcase token.TYPING_SPEED:\n\t\tcmd.Args = p.peek.Literal\n\t\tp.nextToken()\n\t\t// Allow TypingSpeed to have bare units (e.g. 10ms)\n\t\t// Set TypingSpeed 10ms\n\t\tif p.peek.Type == token.MILLISECONDS ||\n\t\t\tp.peek.Type == token.SECONDS {\n\t\t\tcmd.Args += p.peek.Literal\n\t\t\tp.nextToken()\n\t\t} else if cmd.Options == \"TypingSpeed\" {\n\t\t\tcmd.Args += \"s\"\n\t\t}\n\tcase token.WINDOW_BAR:\n\t\tcmd.Args = p.peek.Literal\n\t\tp.nextToken()\n\n\t\twindowBar := p.cur.Literal\n\t\tif !isValidWindowBar(windowBar) {\n\t\t\tp.errors = append(\n\t\t\t\tp.errors,\n\t\t\t\tNewError(p.cur, windowBar+\" is not a valid bar style.\"),\n\t\t\t)\n\t\t}\n\tcase token.MARGIN_FILL:\n\t\tcmd.Args = p.peek.Literal\n\t\tp.nextToken()\n\n\t\tmarginFill := p.cur.Literal\n\n\t\t// Check if margin color is a valid hex string\n\t\tif strings.HasPrefix(marginFill, \"#\") {\n\t\t\t_, err := strconv.ParseUint(marginFill[1:], 16, 64)\n\n\t\t\tif err != nil || len(marginFill) != 7 {\n\t\t\t\tp.errors = append(\n\t\t\t\t\tp.errors,\n\t\t\t\t\tNewError(\n\t\t\t\t\t\tp.cur,\n\t\t\t\t\t\t\"\\\"\"+marginFill+\"\\\" is not a valid color.\",\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\tcase token.CURSOR_BLINK:\n\t\tcmd.Args = p.peek.Literal\n\t\tp.nextToken()\n\n\t\tif p.cur.Type != token.BOOLEAN {\n\t\t\tp.errors = append(\n\t\t\t\tp.errors,\n\t\t\t\tNewError(p.cur, \"expected boolean value.\"),\n\t\t\t)\n\t\t}\n\n\tdefault:\n\t\tcmd.Args = p.peek.Literal\n\t\tp.nextToken()\n\t}\n\n\treturn cmd\n}\n\n// parseSleep parses a sleep command.\n// A sleep command takes a time for how long to sleep.\n//\n//\tSleep <time>\nfunc (p *Parser) parseSleep() Command {\n\tcmd := Command{Type: token.SLEEP}\n\tcmd.Args = p.parseTime()\n\treturn cmd\n}\n\n// parseHide parses a Hide command.\n//\n//\tHide\nfunc (p *Parser) parseHide() Command {\n\tcmd := Command{Type: token.HIDE}\n\treturn cmd\n}\n\n// parseRequire parses a Require command.\n//\n//\tRequire\nfunc (p *Parser) parseRequire() Command {\n\tcmd := Command{Type: token.REQUIRE}\n\n\tif p.peek.Type != token.STRING {\n\t\tp.errors = append(p.errors, NewError(p.peek, p.cur.Literal+\" expects one string\"))\n\t}\n\n\tcmd.Args = p.peek.Literal\n\tp.nextToken()\n\n\treturn cmd\n}\n\n// parseShow parses a Show command.\n//\n//\tShow\nfunc (p *Parser) parseShow() Command {\n\tcmd := Command{Type: token.SHOW}\n\treturn cmd\n}\n\n// parseType parses a type command.\n// A type command takes a string to type.\n//\n//\tType \"string\"\nfunc (p *Parser) parseType() Command {\n\tcmd := Command{Type: token.TYPE}\n\n\tcmd.Options = p.parseSpeed()\n\n\tif p.peek.Type != token.STRING {\n\t\tp.errors = append(p.errors, NewError(p.peek, p.cur.Literal+\" expects string\"))\n\t}\n\n\tfor p.peek.Type == token.STRING {\n\t\tp.nextToken()\n\t\tcmd.Args += p.cur.Literal\n\n\t\t// If the next token is a string, add a space between them.\n\t\t// Since tokens must be separated by a whitespace, this is most likely\n\t\t// what the user intended.\n\t\t//\n\t\t// Although it is possible that there may be multiple spaces / tabs between\n\t\t// the tokens, however if the user was intending to type multiple spaces\n\t\t// they would need to use a string literal.\n\n\t\tif p.peek.Type == token.STRING {\n\t\t\tcmd.Args += \" \"\n\t\t}\n\t}\n\n\treturn cmd\n}\n\n// parseCopy parses a copy command\n// A copy command takes a string to the clipboard\n//\n//\tCopy \"string\"\nfunc (p *Parser) parseCopy() Command {\n\tcmd := Command{Type: token.COPY}\n\n\tif p.peek.Type != token.STRING {\n\t\tp.errors = append(p.errors, NewError(p.peek, p.cur.Literal+\" expects string\"))\n\t}\n\tfor p.peek.Type == token.STRING {\n\t\tp.nextToken()\n\t\tcmd.Args += p.cur.Literal\n\n\t\t// If the next token is a string, add a space between them.\n\t\t// Since tokens must be separated by a whitespace, this is most likely\n\t\t// what the user intended.\n\t\t//\n\t\t// Although it is possible that there may be multiple spaces / tabs between\n\t\t// the tokens, however if the user was intending to type multiple spaces\n\t\t// they would need to use a string literal.\n\n\t\tif p.peek.Type == token.STRING {\n\t\t\tcmd.Args += \" \"\n\t\t}\n\t}\n\treturn cmd\n}\n\n// parsePaste parses paste command\n// Paste Command the string from the clipboard buffer.\n//\n//\tPaste\nfunc (p *Parser) parsePaste() Command {\n\tcmd := Command{Type: token.PASTE}\n\treturn cmd\n}\n\n// parseEnv parses Env command\n// Env command takes in a key-value pair which is set.\n//\n//\tEnv key \"value\"\nfunc (p *Parser) parseEnv() Command {\n\tcmd := Command{Type: token.ENV}\n\n\tcmd.Options = p.peek.Literal\n\tp.nextToken()\n\n\tif p.peek.Type != token.STRING {\n\t\tp.errors = append(p.errors, NewError(p.peek, p.cur.Literal+\" expects string\"))\n\t}\n\n\tcmd.Args = p.peek.Literal\n\tp.nextToken()\n\n\treturn cmd\n}\n\n// parseSource parses source command.\n// Source command takes a tape path to include in current tape.\n//\n//\tSource <path>\nfunc (p *Parser) parseSource() []Command {\n\tcmd := Command{Type: token.SOURCE}\n\n\tif p.peek.Type != token.STRING {\n\t\tp.errors = append(p.errors, NewError(p.cur, \"Expected path after Source\"))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\tsrcPath := p.peek.Literal\n\n\t// Check if path has .tape extension\n\text := filepath.Ext(srcPath)\n\tif ext != \".tape\" {\n\t\tp.errors = append(p.errors, NewError(p.peek, \"Expected file with .tape extension\"))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\t// Check if tape exist\n\tif _, err := os.Stat(srcPath); os.IsNotExist(err) { //nolint:gosec\n\t\tnotFoundErr := fmt.Sprintf(\"File %s not found\", srcPath)\n\t\tp.errors = append(p.errors, NewError(p.peek, notFoundErr))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\t// Check if source tape contains nested Source command\n\td, err := os.ReadFile(srcPath) //nolint:gosec\n\tif err != nil {\n\t\treadErr := fmt.Sprintf(\"Unable to read file: %s\", srcPath)\n\t\tp.errors = append(p.errors, NewError(p.peek, readErr))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\tsrcTape := string(d)\n\t// Check source tape is NOT empty\n\tif len(srcTape) == 0 {\n\t\treadErr := fmt.Sprintf(\"Source tape: %s is empty\", srcPath)\n\t\tp.errors = append(p.errors, NewError(p.peek, readErr))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\tsrcLexer := lexer.New(srcTape)\n\tsrcParser := New(srcLexer)\n\n\t// Check not nested source\n\tsrcCmds := srcParser.Parse()\n\tfor _, cmd := range srcCmds {\n\t\tif cmd.Type == token.SOURCE {\n\t\t\tp.errors = append(p.errors, NewError(p.peek, \"Nested Source detected\"))\n\t\t\tp.nextToken()\n\t\t\treturn []Command{cmd}\n\t\t}\n\t}\n\n\t// Check src errors\n\tsrcErrors := srcParser.Errors()\n\tif len(srcErrors) > 0 {\n\t\tp.errors = append(p.errors, NewError(p.peek, fmt.Sprintf(\"%s has %d errors\", srcPath, len(srcErrors))))\n\t\tp.nextToken()\n\t\treturn []Command{cmd}\n\t}\n\n\tfiltered := make([]Command, 0)\n\tfor _, srcCmd := range srcCmds {\n\t\t// Output have to be avoid in order to not overwrite output of the original tape.\n\t\tif srcCmd.Type == token.SOURCE ||\n\t\t\tsrcCmd.Type == token.OUTPUT {\n\t\t\tcontinue\n\t\t}\n\t\tfiltered = append(filtered, srcCmd)\n\t}\n\n\tp.nextToken()\n\treturn filtered\n}\n\n// parseScreenshot parses screenshot command.\n// Screenshot command takes a file path for storing screenshot.\n//\n//\tScreenshot <path>\nfunc (p *Parser) parseScreenshot() Command {\n\tcmd := Command{Type: token.SCREENSHOT}\n\n\tif p.peek.Type != token.STRING {\n\t\tp.errors = append(p.errors, NewError(p.cur, \"Expected path after Screenshot\"))\n\t\tp.nextToken()\n\t\treturn cmd\n\t}\n\n\tpath := p.peek.Literal\n\n\t// Check if path has .png extension\n\text := filepath.Ext(path)\n\tif ext != \".png\" {\n\t\tp.errors = append(p.errors, NewError(p.peek, \"Expected file with .png extension\"))\n\t\tp.nextToken()\n\t\treturn cmd\n\t}\n\n\tcmd.Args = path\n\tp.nextToken()\n\n\treturn cmd\n}\n\n// Errors returns any errors that occurred during parsing.\nfunc (p *Parser) Errors() []Error {\n\treturn p.errors\n}\n\n// nextToken gets the next token from the lexer\n// and updates the parser tokens accordingly.\nfunc (p *Parser) nextToken() {\n\tp.cur = p.peek\n\tp.peek = p.l.NextToken()\n}\n\n// Check if a given windowbar type is valid.\nfunc isValidWindowBar(w string) bool {\n\treturn w == \"\" ||\n\t\tw == \"Colorful\" || w == \"ColorfulRight\" ||\n\t\tw == \"Rings\" || w == \"RingsRight\"\n}\n"
  },
  {
    "path": "parser/parser_test.go",
    "content": "package parser\n\nimport (\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/charmbracelet/vhs/lexer\"\n\t\"github.com/charmbracelet/vhs/token\"\n)\n\nfunc TestParser(t *testing.T) {\n\tinput := `\nSet TypingSpeed 100ms\nSet WaitTimeout 1m\nSet WaitPattern /foo/\nType \"echo 'Hello, World!'\"\nEnter\nBackspace@0.1 5\nBackspace@.1 5\nBackspace@1 5\nBackspace@100ms 5\nDelete 2\nInsert 2\nRight 3\nLeft 3\nUp@50ms\nDown 2\nScrollUp 4\nScrollDown@100ms 2\nCtrl+C\nCtrl+L\nAlt+.\nSleep 100ms\nSleep 3\nWait\nWait+Screen\nWait@100ms /foobar/`\n\n\texpected := []Command{\n\t\t{Type: token.SET, Options: \"TypingSpeed\", Args: \"100ms\"},\n\t\t{Type: token.SET, Options: \"WaitTimeout\", Args: \"1m\"},\n\t\t{Type: token.SET, Options: \"WaitPattern\", Args: \"foo\"},\n\t\t{Type: token.TYPE, Options: \"\", Args: \"echo 'Hello, World!'\"},\n\t\t{Type: token.ENTER, Options: \"\", Args: \"1\"},\n\t\t{Type: token.BACKSPACE, Options: \"0.1s\", Args: \"5\"},\n\t\t{Type: token.BACKSPACE, Options: \".1s\", Args: \"5\"},\n\t\t{Type: token.BACKSPACE, Options: \"1s\", Args: \"5\"},\n\t\t{Type: token.BACKSPACE, Options: \"100ms\", Args: \"5\"},\n\t\t{Type: token.DELETE, Options: \"\", Args: \"2\"},\n\t\t{Type: token.INSERT, Options: \"\", Args: \"2\"},\n\t\t{Type: token.RIGHT, Options: \"\", Args: \"3\"},\n\t\t{Type: token.LEFT, Options: \"\", Args: \"3\"},\n\t\t{Type: token.UP, Options: \"50ms\", Args: \"1\"},\n\t\t{Type: token.DOWN, Options: \"\", Args: \"2\"},\n\t\t{Type: token.SCROLL_UP, Options: \"\", Args: \"4\"},\n\t\t{Type: token.SCROLL_DOWN, Options: \"100ms\", Args: \"2\"},\n\t\t{Type: token.CTRL, Options: \"\", Args: \"C\"},\n\t\t{Type: token.CTRL, Options: \"\", Args: \"L\"},\n\t\t{Type: token.ALT, Options: \"\", Args: \".\"},\n\t\t{Type: token.SLEEP, Args: \"100ms\"},\n\t\t{Type: token.SLEEP, Args: \"3s\"},\n\t\t{Type: token.WAIT, Args: \"Line\"},\n\t\t{Type: token.WAIT, Args: \"Screen\"},\n\t\t{Type: token.WAIT, Options: \"100ms\", Args: \"Line foobar\"},\n\t}\n\n\tl := lexer.New(input)\n\tp := New(l)\n\n\tcmds := p.Parse()\n\n\tif len(cmds) != len(expected) {\n\t\tt.Fatalf(\"Expected %d commands, got %d; %v\", len(expected), len(cmds), cmds)\n\t}\n\n\tfor i, cmd := range cmds {\n\t\tif cmd.Type != expected[i].Type {\n\t\t\tt.Errorf(\"Expected command %d to be %s, got %s\", i, expected[i].Type, cmd.Type)\n\t\t}\n\t\tif cmd.Args != expected[i].Args {\n\t\t\tt.Errorf(\"Expected command %d to have args %s, got %s\", i, expected[i].Args, cmd.Args)\n\t\t}\n\t\tif cmd.Options != expected[i].Options {\n\t\t\tt.Errorf(\"Expected command %d to have options %s, got %s\", i, expected[i].Options, cmd.Options)\n\t\t}\n\t}\n}\n\nfunc TestParserErrors(t *testing.T) {\n\tinput := `\nType Enter\nType \"echo 'Hello, World!'\" Enter\nFoo\nSleep Bar`\n\n\tl := lexer.New(input)\n\tp := New(l)\n\n\t_ = p.Parse()\n\n\texpectedErrors := []string{\n\t\t\" 2:6  │ Type expects string\",\n\t\t\" 4:1  │ Invalid command: Foo\",\n\t\t\" 5:1  │ Expected time after Sleep\",\n\t\t\" 5:7  │ Invalid command: Bar\",\n\t}\n\n\tif len(p.errors) != len(expectedErrors) {\n\t\tt.Fatalf(\"Expected %d errors, got %d\", len(expectedErrors), len(p.errors))\n\t}\n\n\tfor i, err := range p.errors {\n\t\tif err.String() != expectedErrors[i] {\n\t\t\tt.Errorf(\"Expected error %d to be [%s], got (%s)\", i, expectedErrors[i], err)\n\t\t}\n\t}\n}\n\nfunc TestParseTapeFile(t *testing.T) {\n\tinput, err := os.ReadFile(\"../examples/fixtures/all.tape\")\n\tif err != nil {\n\t\tt.Fatal(\"could not read fixture file\")\n\t}\n\n\texpected := []Command{\n\t\t{Type: token.OUTPUT, Options: \".gif\", Args: \"examples/fixtures/all.gif\"},\n\t\t{Type: token.OUTPUT, Options: \".mp4\", Args: \"examples/fixtures/all.mp4\"},\n\t\t{Type: token.OUTPUT, Options: \".webm\", Args: \"examples/fixtures/all.webm\"},\n\t\t{Type: token.SET, Options: \"Shell\", Args: \"fish\"},\n\t\t{Type: token.SET, Options: \"FontSize\", Args: \"22\"},\n\t\t{Type: token.SET, Options: \"FontFamily\", Args: \"DejaVu Sans Mono\"},\n\t\t{Type: token.SET, Options: \"Height\", Args: \"600\"},\n\t\t{Type: token.SET, Options: \"Width\", Args: \"1200\"},\n\t\t{Type: token.SET, Options: \"LetterSpacing\", Args: \"1\"},\n\t\t{Type: token.SET, Options: \"LineHeight\", Args: \"1.2\"},\n\t\t{Type: token.SET, Options: \"Theme\", Args: \"{ \\\"name\\\": \\\"Whimsy\\\", \\\"black\\\": \\\"#535178\\\", \\\"red\\\": \\\"#ef6487\\\", \\\"green\\\": \\\"#5eca89\\\", \\\"yellow\\\": \\\"#fdd877\\\", \\\"blue\\\": \\\"#65aef7\\\", \\\"purple\\\": \\\"#aa7ff0\\\", \\\"cyan\\\": \\\"#43c1be\\\", \\\"white\\\": \\\"#ffffff\\\", \\\"brightBlack\\\": \\\"#535178\\\", \\\"brightRed\\\": \\\"#ef6487\\\", \\\"brightGreen\\\": \\\"#5eca89\\\", \\\"brightYellow\\\": \\\"#fdd877\\\", \\\"brightBlue\\\": \\\"#65aef7\\\", \\\"brightPurple\\\": \\\"#aa7ff0\\\", \\\"brightCyan\\\": \\\"#43c1be\\\", \\\"brightWhite\\\": \\\"#ffffff\\\", \\\"background\\\": \\\"#29283b\\\", \\\"foreground\\\": \\\"#b3b0d6\\\", \\\"selectionBackground\\\": \\\"#3d3c58\\\", \\\"cursorColor\\\": \\\"#b3b0d6\\\" }\"},\n\t\t{Type: token.SET, Options: \"Theme\", Args: \"Catppuccin Mocha\"},\n\t\t{Type: token.SET, Options: \"Padding\", Args: \"50\"},\n\t\t{Type: token.SET, Options: \"Framerate\", Args: \"60\"},\n\t\t{Type: token.SET, Options: \"PlaybackSpeed\", Args: \"2\"},\n\t\t{Type: token.SET, Options: \"TypingSpeed\", Args: \".1s\"},\n\t\t{Type: token.SET, Options: \"LoopOffset\", Args: \"60.4%\"},\n\t\t{Type: token.SET, Options: \"LoopOffset\", Args: \"20.99%\"},\n\t\t{Type: token.SET, Options: \"CursorBlink\", Args: \"false\"},\n\t\t{Type: token.SLEEP, Options: \"\", Args: \"1s\"},\n\t\t{Type: token.SLEEP, Options: \"\", Args: \"500ms\"},\n\t\t{Type: token.SLEEP, Options: \"\", Args: \".5s\"},\n\t\t{Type: token.SLEEP, Options: \"\", Args: \"0.5s\"},\n\t\t{Type: token.TYPE, Options: \".5s\", Args: \"All\"},\n\t\t{Type: token.TYPE, Options: \"500ms\", Args: \"All\"},\n\t\t{Type: token.TYPE, Options: \"\", Args: \"Double Quote\"},\n\t\t{Type: token.TYPE, Options: \"\", Args: \"\\\"Single\\\" Quote\"},\n\t\t{Type: token.TYPE, Options: \"\", Args: `\"Backtick\" 'Quote'`},\n\t\t{Type: token.BACKSPACE, Options: \"\", Args: \"1\"},\n\t\t{Type: token.BACKSPACE, Options: \"\", Args: \"2\"},\n\t\t{Type: token.BACKSPACE, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.DELETE, Options: \"\", Args: \"1\"},\n\t\t{Type: token.DELETE, Options: \"\", Args: \"2\"},\n\t\t{Type: token.DELETE, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.INSERT, Options: \"\", Args: \"1\"},\n\t\t{Type: token.INSERT, Options: \"\", Args: \"2\"},\n\t\t{Type: token.INSERT, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.DOWN, Options: \"\", Args: \"1\"},\n\t\t{Type: token.DOWN, Options: \"\", Args: \"2\"},\n\t\t{Type: token.DOWN, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.PAGE_DOWN, Options: \"\", Args: \"1\"},\n\t\t{Type: token.PAGE_DOWN, Options: \"\", Args: \"2\"},\n\t\t{Type: token.PAGE_DOWN, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.SCROLL_DOWN, Options: \"\", Args: \"1\"},\n\t\t{Type: token.SCROLL_DOWN, Options: \"\", Args: \"2\"},\n\t\t{Type: token.SCROLL_DOWN, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.ENTER, Options: \"\", Args: \"1\"},\n\t\t{Type: token.ENTER, Options: \"\", Args: \"2\"},\n\t\t{Type: token.ENTER, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.SPACE, Options: \"\", Args: \"1\"},\n\t\t{Type: token.SPACE, Options: \"\", Args: \"2\"},\n\t\t{Type: token.SPACE, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.TAB, Options: \"\", Args: \"1\"},\n\t\t{Type: token.TAB, Options: \"\", Args: \"2\"},\n\t\t{Type: token.TAB, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.LEFT, Options: \"\", Args: \"1\"},\n\t\t{Type: token.LEFT, Options: \"\", Args: \"2\"},\n\t\t{Type: token.LEFT, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.RIGHT, Options: \"\", Args: \"1\"},\n\t\t{Type: token.RIGHT, Options: \"\", Args: \"2\"},\n\t\t{Type: token.RIGHT, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.UP, Options: \"\", Args: \"1\"},\n\t\t{Type: token.UP, Options: \"\", Args: \"2\"},\n\t\t{Type: token.UP, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.PAGE_UP, Options: \"\", Args: \"1\"},\n\t\t{Type: token.PAGE_UP, Options: \"\", Args: \"2\"},\n\t\t{Type: token.PAGE_UP, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.SCROLL_UP, Options: \"\", Args: \"1\"},\n\t\t{Type: token.SCROLL_UP, Options: \"\", Args: \"2\"},\n\t\t{Type: token.SCROLL_UP, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.DOWN, Options: \"\", Args: \"1\"},\n\t\t{Type: token.DOWN, Options: \"\", Args: \"2\"},\n\t\t{Type: token.DOWN, Options: \"1s\", Args: \"3\"},\n\t\t{Type: token.CTRL, Options: \"\", Args: \"C\"},\n\t\t{Type: token.CTRL, Options: \"\", Args: \"L\"},\n\t\t{Type: token.CTRL, Options: \"\", Args: \"R\"},\n\t\t{Type: token.ALT, Options: \"\", Args: \".\"},\n\t\t{Type: token.ALT, Options: \"\", Args: \"L\"},\n\t\t{Type: token.ALT, Options: \"\", Args: \"i\"},\n\t\t{Type: token.HIDE, Options: \"\", Args: \"\"},\n\t\t{Type: token.SHOW, Options: \"\", Args: \"\"},\n\t}\n\n\tl := lexer.New(string(input))\n\tp := New(l)\n\n\tcmds := p.Parse()\n\n\tif len(cmds) != len(expected) {\n\t\tt.Fatalf(\"Expected %d commands, got %d\", len(expected), len(cmds))\n\t}\n\n\tfor i, cmd := range cmds {\n\t\tif cmd.Type != expected[i].Type {\n\t\t\tt.Errorf(\"Expected command %d to be %s, got %s\", i, expected[i].Type, cmd.Type)\n\t\t}\n\t\tif cmd.Args != expected[i].Args {\n\t\t\tt.Errorf(\"Expected command %d to have args %s, got %s\", i, expected[i].Args, cmd.Args)\n\t\t}\n\t\tif cmd.Options != expected[i].Options {\n\t\t\tt.Errorf(\"Expected command %d to have options %s, got %s\", i, expected[i].Options, cmd.Options)\n\t\t}\n\t}\n}\n\nfunc TestParseCtrl(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\ttape     string\n\t\twantArgs []string\n\t\twantErr  bool\n\t}{\n\t\t{\n\t\t\tname:     \"should parse with multiple modifiers\",\n\t\t\ttape:     \"Ctrl+Shift+Alt+C\",\n\t\t\twantArgs: []string{\"Shift\", \"Alt\", \"C\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:    \"should not parse with out of order modifiers\",\n\t\t\ttape:    \"Ctrl+Shift+C+Alt\",\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname:    \"should not parse with out of order modifiers\",\n\t\t\ttape:    \"Ctrl+Shift+C+Alt+C\",\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Left\",\n\t\t\ttape:     \"Ctrl+Left\",\n\t\t\twantArgs: []string{\"Left\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Right\",\n\t\t\ttape:     \"Ctrl+Right\",\n\t\t\twantArgs: []string{\"Right\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Up\",\n\t\t\ttape:     \"Ctrl+Up\",\n\t\t\twantArgs: []string{\"Up\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Down\",\n\t\t\ttape:     \"Ctrl+Down\",\n\t\t\twantArgs: []string{\"Down\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Alt+Left\",\n\t\t\ttape:     \"Ctrl+Alt+Left\",\n\t\t\twantArgs: []string{\"Alt\", \"Left\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Alt+Right\",\n\t\t\ttape:     \"Ctrl+Alt+Right\",\n\t\t\twantArgs: []string{\"Alt\", \"Right\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Alt+Up\",\n\t\t\ttape:     \"Ctrl+Alt+Up\",\n\t\t\twantArgs: []string{\"Alt\", \"Up\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should parse Ctrl+Alt+Down\",\n\t\t\ttape:     \"Ctrl+Alt+Down\",\n\t\t\twantArgs: []string{\"Alt\", \"Down\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"Ctrl+Backspace\",\n\t\t\ttape:     \"Ctrl+Backspace\",\n\t\t\twantArgs: []string{\"Backspace\"},\n\t\t\twantErr:  false,\n\t\t},\n\t\t{\n\t\t\tname:     \"Ctrl+Space\",\n\t\t\ttape:     \"Ctrl+Space\",\n\t\t\twantArgs: []string{\"Space\"},\n\t\t\twantErr:  false,\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tl := lexer.New(tc.tape)\n\t\t\tp := New(l)\n\n\t\t\tcmd := p.parseCtrl()\n\t\t\tif tc.wantErr {\n\t\t\t\tif len(p.errors) == 0 {\n\t\t\t\t\tt.Errorf(\"Expected to parse with errors but was success\")\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif len(p.errors) > 0 {\n\t\t\t\tt.Errorf(\"Expected to parse with no errors but was failure\")\n\t\t\t}\n\n\t\t\targs := strings.Split(cmd.Args, \" \")\n\t\t\tif len(tc.wantArgs) != len(args) {\n\t\t\t\tt.Fatalf(\"Unable to parse args, expected args %d, got %d\", len(tc.wantArgs), len(args))\n\t\t\t}\n\n\t\t\tfor i, arg := range args {\n\t\t\t\tif tc.wantArgs[i] != arg {\n\t\t\t\t\tt.Errorf(\"Arg %d is wrong, expected %s, got %s\", i, tc.wantArgs[i], arg)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\ntype parseSourceTest struct {\n\ttape      string\n\tsrcTape   string\n\terrors    []string\n\twriteFile bool\n}\n\nfunc (st *parseSourceTest) run(t *testing.T) {\n\tif st.writeFile {\n\t\terr := os.WriteFile(\"source.tape\", []byte(st.srcTape), os.ModePerm)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\tl := lexer.New(st.tape)\n\tp := New(l)\n\n\t_ = p.Parse()\n\n\tif len(p.errors) != len(st.errors) {\n\t\tt.Fatalf(\"Expected errors: %d, errors: %d\", len(st.errors), len(p.errors))\n\t}\n\n\tfor i := range st.errors {\n\t\terr := p.errors[i].Msg\n\t\texpected := st.errors[i]\n\n\t\tif err != expected {\n\t\t\tt.Errorf(\"Expected error: %s, actual error %s\", expected, err)\n\t\t}\n\t}\n\n\tos.Remove(\"source.tape\")\n}\n\nfunc TestParseSource(t *testing.T) {\n\tt.Run(\"should not return errors when tape exist and is NOT empty\", func(t *testing.T) {\n\t\ttest := &parseSourceTest{\n\t\t\ttape:      \"Source source.tape\",\n\t\t\tsrcTape:   `Type \"echo 'Welcome to VHS!'\"`,\n\t\t\twriteFile: true,\n\t\t}\n\n\t\ttest.run(t)\n\t})\n\n\tt.Run(\"should return errors when tape NOT found\", func(t *testing.T) {\n\t\ttest := &parseSourceTest{\n\t\t\ttape:      \"Source source.tape\",\n\t\t\terrors:    []string{\"File source.tape not found\"},\n\t\t\twriteFile: false,\n\t\t}\n\n\t\ttest.run(t)\n\t})\n\n\tt.Run(\"should return error when tape extension is NOT (.tape)\", func(t *testing.T) {\n\t\ttest := &parseSourceTest{\n\t\t\ttape:      \"Source source.vhs\",\n\t\t\terrors:    []string{\"Expected file with .tape extension\"},\n\t\t\twriteFile: true,\n\t\t}\n\n\t\ttest.run(t)\n\t})\n\n\tt.Run(\"should return error when Source command does NOT have tape path\", func(t *testing.T) {\n\t\ttest := &parseSourceTest{\n\t\t\ttape:      \"Source\",\n\t\t\terrors:    []string{\"Expected path after Source\"},\n\t\t\twriteFile: true,\n\t\t}\n\n\t\ttest.run(t)\n\t})\n\n\tt.Run(\"should return error when find nested Source commands\", func(t *testing.T) {\n\t\ttest := &parseSourceTest{\n\t\t\ttape: \"Source source.tape\",\n\t\t\tsrcTape: `Type \"echo 'Welcome to VHS!'\"\n\tSource magic.tape\n\tType \"goodbye\"\n\t`,\n\t\t\terrors:    []string{\"Nested Source detected\"},\n\t\t\twriteFile: true,\n\t\t}\n\n\t\ttest.run(t)\n\t})\n}\n\ntype parseScreenshotTest struct {\n\ttape   string\n\terrors []string\n}\n\nfunc (st *parseScreenshotTest) run(t *testing.T) {\n\tl := lexer.New(st.tape)\n\tp := New(l)\n\n\t_ = p.Parse()\n\n\tif len(p.errors) != len(st.errors) {\n\t\tt.Fatalf(\"Expected errors: %d, errors: %d\", len(st.errors), len(p.errors))\n\t}\n\n\tfor i := range st.errors {\n\t\terr := p.errors[i].Msg\n\t\texpected := st.errors[i]\n\n\t\tif err != expected {\n\t\t\tt.Errorf(\"Expected error: %s, actual error %s\", expected, err)\n\t\t}\n\t}\n}\n\nfunc TestParseScreeenshot(t *testing.T) {\n\tt.Run(\"should return error when screenshot extension is NOT (.png)\", func(t *testing.T) {\n\t\ttest := &parseScreenshotTest{\n\t\t\ttape:   \"Screenshot step_one_screenshot.jpg\",\n\t\t\terrors: []string{\"Expected file with .png extension\"},\n\t\t}\n\n\t\ttest.run(t)\n\t})\n\n\tt.Run(\"should return error when screenshot path is missing\", func(t *testing.T) {\n\t\ttest := &parseScreenshotTest{\n\t\t\ttape:   \"Screenshot\",\n\t\t\terrors: []string{\"Expected path after Screenshot\"},\n\t\t}\n\n\t\ttest.run(t)\n\t})\n}\n"
  },
  {
    "path": "publish.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/keygen\"\n\t\"github.com/mattn/go-isatty\"\n\tgap \"github.com/muesli/go-app-paths\"\n\t\"github.com/spf13/cobra\"\n\t\"golang.org/x/crypto/ssh\"\n\t\"golang.org/x/crypto/ssh/knownhosts\"\n)\n\nconst (\n\tghostHost = \"ghost.charm.sh\"\n\tghostPort = 22\n)\n\nvar publishCmd = &cobra.Command{\n\tUse:           \"publish <gif>\",\n\tShort:         \"Publish your GIF to vhs.charm.sh and get a shareable URL\",\n\tArgs:          cobra.ExactArgs(1),\n\tSilenceUsage:  true,\n\tSilenceErrors: true, // we print our own errors\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\tfile := args[0]\n\t\tif strings.HasSuffix(file, \".tape\") {\n\t\t\tlog.Printf(\"Use vhs %s --publish flag to publish tapes\\n\", file)\n\t\t\treturn errors.New(\"must pass a GIF file\")\n\t\t}\n\t\tif !strings.HasSuffix(file, gif) {\n\t\t\treturn errors.New(\"must pass a GIF file\")\n\t\t}\n\n\t\turl, err := Publish(cmd.Context(), file)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif quietFlag || !isatty.IsTerminal(os.Stdout.Fd()) {\n\t\t\tfmt.Println(url)\n\t\t\treturn nil\n\t\t}\n\t\tpublishShareInstructions(url)\n\t\tcmd.Print(\"  \" + URLStyle.Render(url))\n\t\tcmd.Println()\n\t\treturn nil\n\t},\n}\n\n//nolint:wrapcheck\nfunc dataPath() (string, error) {\n\tscope := gap.NewScope(gap.User, \"vhs\")\n\tdataPath, err := scope.DataPath(\"\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn dataPath, nil\n}\n\n// hostKeyCallback returns a callback that will be used to verify the host key.\n//\n// it creates a file in the given path, and uses that to verify hosts and keys.\n// if the host does not exist there, it adds it so its available next time, as plain old `ssh` does.\nfunc hostKeyCallback(path string) ssh.HostKeyCallback {\n\treturn func(hostname string, remote net.Addr, key ssh.PublicKey) error {\n\t\tkh, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:mnd\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to open known_hosts: %w\", err)\n\t\t}\n\t\tdefer func() { _ = kh.Close() }()\n\n\t\tcallback, err := knownhosts.New(kh.Name())\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to check known_hosts: %w\", err)\n\t\t}\n\n\t\tif err := callback(hostname, remote, key); err != nil {\n\t\t\tvar kerr *knownhosts.KeyError\n\t\t\tif errors.As(err, &kerr) {\n\t\t\t\tif len(kerr.Want) > 0 {\n\t\t\t\t\treturn fmt.Errorf(\"possible man-in-the-middle attack: %w\", err)\n\t\t\t\t}\n\t\t\t\t// if want is empty, it means the host was not in the known_hosts file, so lets add it there.\n\t\t\t\t_, _ = fmt.Fprintln(kh, knownhosts.Line([]string{hostname}, key))\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"failed to check known_hosts: %w\", err)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n//nolint:wrapcheck\nfunc sshSession() (*ssh.Session, error) {\n\tdp, err := dataPath()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tkp, err := keygen.New(filepath.Join(dp, \"vhs_ed25519\"), keygen.WithKeyType(keygen.Ed25519), keygen.WithWrite())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsigner, err := ssh.NewSignerFromKey(kp.PrivateKey())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpkam := ssh.PublicKeys(signer)\n\tsshConfig := &ssh.ClientConfig{\n\t\tUser:            \"vhs\",\n\t\tAuth:            []ssh.AuthMethod{pkam},\n\t\tHostKeyCallback: hostKeyCallback(filepath.Join(dp, \"known_hosts\")),\n\t}\n\n\tc, err := ssh.Dial(\"tcp\", fmt.Sprintf(\"%s:%d\", ghostHost, ghostPort), sshConfig)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ts, err := c.NewSession()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn s, nil\n}\n\n// publishShareInstructions log shareable URL\n// If log level is set to `logLevelQuiet` the log message will be forced.\nfunc publishShareInstructions(url string) {\n\tlog.Println(\"\\n\" + GrayStyle.Render(\"  Share your GIF with Markdown:\"))\n\tlog.Println(CommandStyle.Render(\"  ![Made with VHS]\") + URLStyle.Render(\"(\"+url+\")\"))\n\tlog.Println(GrayStyle.Render(\"\\n  Or HTML (with badge):\"))\n\tlog.Println(CommandStyle.Render(\"  <img \") + CommandStyle.Render(\"src=\") + URLStyle.Render(`\"`+url+`\"`) + CommandStyle.Render(\" alt=\") + URLStyle.Render(`\"Made with VHS\"`) + CommandStyle.Render(\">\"))\n\tlog.Println(CommandStyle.Render(\"  <a \") + CommandStyle.Render(\"href=\") + URLStyle.Render(`\"https://vhs.charm.sh\"`) + CommandStyle.Render(\">\"))\n\tlog.Println(CommandStyle.Render(\"    <img \") + CommandStyle.Render(\"src=\") + URLStyle.Render(`\"https://stuff.charm.sh/vhs/badge.svg\"`) + CommandStyle.Render(\">\"))\n\tlog.Println(CommandStyle.Render(\"  </a>\"))\n\tlog.Println(GrayStyle.Render(\"\\n  Or link to it:\"))\n}\n\n// Publish publishes the given GIF file to the web.\n//\n//nolint:wrapcheck\nfunc Publish(ctx context.Context, path string) (string, error) {\n\ts, err := sshSession()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer s.Close() //nolint:errcheck\n\n\t// Close connection when context is done\n\tgo func() {\n\t\t<-ctx.Done()\n\t\t_ = s.Close()\n\t}()\n\n\tin, err := s.StdinPipe()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tout, err := s.StdoutPipe()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer f.Close() //nolint:errcheck\n\n\tif err := s.Start(\"\"); err != nil {\n\t\treturn \"\", err\n\t}\n\n\t_, err = io.Copy(in, f)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t_ = in.Close()\n\n\tb, err := io.ReadAll(out)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn string(b), nil\n}\n"
  },
  {
    "path": "record.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/charmbracelet/vhs/token\"\n\t\"github.com/creack/pty\"\n\t\"github.com/spf13/cobra\"\n\t\"golang.org/x/term\"\n)\n\n// sleepThreshold is the time at which if there has been no activity in the\n// tape file we insert a Sleep command.\nconst sleepThreshold = 500 * time.Millisecond\n\n// EscapeSequences is a map of escape sequences to their VHS commands.\nvar EscapeSequences = map[string]string{\n\t\"\\x1b[A\":  token.UP,\n\t\"\\x1b[B\":  token.DOWN,\n\t\"\\x1b[C\":  token.RIGHT,\n\t\"\\x1b[D\":  token.LEFT,\n\t\"\\x1b[1~\": token.HOME,\n\t\"\\x1b[2~\": token.INSERT,\n\t\"\\x1b[3~\": token.DELETE,\n\t\"\\x1b[4~\": token.END,\n\t\"\\x1b[5~\": token.PAGE_UP,\n\t\"\\x1b[6~\": token.PAGE_DOWN,\n\t\"\\x01\":    token.CTRL + \"+A\",\n\t\"\\x02\":    token.CTRL + \"+B\",\n\t\"\\x03\":    token.CTRL + \"+C\",\n\t\"\\x04\":    token.CTRL + \"+D\",\n\t\"\\x05\":    token.CTRL + \"+E\",\n\t\"\\x06\":    token.CTRL + \"+F\",\n\t\"\\x07\":    token.CTRL + \"+G\",\n\t\"\\x08\":    token.BACKSPACE,\n\t\"\\x09\":    token.TAB,\n\t\"\\x0b\":    token.CTRL + \"+K\",\n\t\"\\x0c\":    token.CTRL + \"+L\",\n\t\"\\x0d\":    token.ENTER,\n\t\"\\x0e\":    token.CTRL + \"+N\",\n\t\"\\x0f\":    token.CTRL + \"+O\",\n\t\"\\x10\":    token.CTRL + \"+P\",\n\t\"\\x11\":    token.CTRL + \"+Q\",\n\t\"\\x12\":    token.CTRL + \"+R\",\n\t\"\\x13\":    token.CTRL + \"+S\",\n\t\"\\x14\":    token.CTRL + \"+T\",\n\t\"\\x15\":    token.CTRL + \"+U\",\n\t\"\\x16\":    token.CTRL + \"+V\",\n\t\"\\x17\":    token.CTRL + \"+W\",\n\t\"\\x18\":    token.CTRL + \"+X\",\n\t\"\\x19\":    token.CTRL + \"+Y\",\n\t\"\\x1a\":    token.CTRL + \"+Z\",\n\t\"\\x1b\":    token.ESCAPE,\n\t\"\\x7f\":    token.BACKSPACE,\n}\n\n// Record is a command that starts a pseudo-terminal for the user to begin\n// writing to, it records all the key presses on stdin and uses them to write\n// Tape commands.\n//\n//\tvhs record > file.tape\n//\n//nolint:wrapcheck\nfunc Record(_ *cobra.Command, _ []string) error {\n\tcommand := exec.Command(shell)\n\n\tcommand.Env = append(os.Environ(), \"VHS_RECORD=true\")\n\n\tterminal, err := pty.Start(command)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := pty.InheritSize(os.Stdin, terminal); err != nil {\n\t\tlog.Printf(\"error resizing pty: %s\", err)\n\t}\n\n\tprevState, err := term.MakeRaw(int(os.Stdin.Fd()))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// We'll need to display the stdin on the screen but we'll also need a copy to\n\t// analyze later and create a tape file.\n\ttape := &bytes.Buffer{}\n\tin := io.MultiWriter(tape, terminal)\n\n\tif shell != defaultShell {\n\t\t_, _ = fmt.Fprintf(tape, \"%s Shell %s\\n\", token.SET, shell)\n\t}\n\n\tgo func() {\n\t\tvar length int\n\t\tfor {\n\t\t\tlength = tape.Len()\n\t\t\ttime.Sleep(sleepThreshold)\n\t\t\tif length == tape.Len() {\n\t\t\t\t// Tape has not changed in a while, write a Sleep command.\n\t\t\t\t_, _ = fmt.Fprintf(tape, \"\\n%s\\n\", token.SLEEP)\n\t\t\t}\n\t\t}\n\t}()\n\n\t// Write to the buffer and PTY's stdin and stderr so that stdout is reserved\n\t// for the output tape file.\n\tgo func() { _, _ = io.Copy(in, os.Stdin) }()\n\t_, _ = io.Copy(os.Stderr, terminal)\n\n\t// PTY cleanup and restore terminal\n\t_ = terminal.Close()\n\t_ = term.Restore(int(os.Stdin.Fd()), prevState)\n\n\tfmt.Println(inputToTape(tape.String()))\n\treturn nil\n}\n\nvar (\n\tcursorResponse = regexp.MustCompile(`\\x1b\\[\\d+;\\d+R`)\n\toscResponse    = regexp.MustCompile(`\\x1b\\]\\d+;rgb:....\\/....\\/....(\\x07|\\x1b\\\\)`)\n)\n\n// inputToTape takes input from a PTY stdin and converts it into a tape file.\nfunc inputToTape(input string) string {\n\t// If the user exited the shell by typing exit don't record this in the\n\t// command.\n\t//\n\t// NOTE: this is not very robust as if someone types exii<BS>t it will not work\n\t// correctly and the exit will show up. In this case, the user should edit the\n\t// tape file.\n\ts := strings.TrimSuffix(strings.TrimSpace(input), \"exit\")\n\n\t// Remove cursor / osc responses\n\ts = cursorResponse.ReplaceAllString(s, \"\")\n\ts = oscResponse.ReplaceAllString(s, \"\")\n\n\t// Substitute escape sequences for commands\n\tfor sequence, command := range EscapeSequences {\n\t\ts = strings.ReplaceAll(s, sequence, \"\\n\"+command+\"\\n\")\n\t}\n\n\ts = strings.ReplaceAll(s, \"\\n\\n\", \"\\n\")\n\n\tvar sanitized strings.Builder\n\tlines := strings.Split(s, \"\\n\")\n\n\tfor i := 0; i < len(lines)-1; i++ {\n\t\t// Group repeated commands to compress file and make it more readable.\n\t\trepeat := 1\n\t\tfor lines[i] == lines[i+repeat] {\n\t\t\trepeat++\n\t\t\tif i+repeat == len(lines) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\ti += repeat - 1\n\n\t\t// We've encountered some non-command, assume that we need to type these\n\t\t// characters.\n\t\tif token.Type(lines[i]) == token.SLEEP { //nolint:nestif\n\t\t\tsleep := sleepThreshold * time.Duration(repeat)\n\t\t\tif sleep >= time.Minute {\n\t\t\t\t_, _ = fmt.Fprintf(&sanitized, \"%s %gs\", token.Type(token.SLEEP), sleep.Seconds())\n\t\t\t} else {\n\t\t\t\t_, _ = fmt.Fprintf(&sanitized, \"%s %s\", token.Type(token.SLEEP), sleep)\n\t\t\t}\n\t\t} else if strings.HasPrefix(lines[i], token.CTRL) {\n\t\t\tfor j := 0; j < repeat; j++ {\n\t\t\t\tsanitized.WriteString(\"Ctrl\" + strings.TrimPrefix(lines[i], token.CTRL) + \"\\n\")\n\t\t\t}\n\t\t\tcontinue\n\t\t} else if strings.HasPrefix(lines[i], token.ALT) {\n\t\t\tfor j := 0; j < repeat; j++ {\n\t\t\t\tsanitized.WriteString(\"Alt\" + strings.TrimPrefix(lines[i], token.ALT) + \"\\n\")\n\t\t\t}\n\t\t\tcontinue\n\t\t} else if strings.HasPrefix(lines[i], token.SET) {\n\t\t\tsanitized.WriteString(\"Set\" + strings.TrimPrefix(lines[i], token.SET))\n\t\t} else if token.IsCommand(token.Type(lines[i])) {\n\t\t\t_, _ = fmt.Fprint(&sanitized, token.Type(lines[i]))\n\t\t\tif repeat > 1 {\n\t\t\t\t_, _ = fmt.Fprint(&sanitized, \" \", repeat)\n\t\t\t}\n\t\t} else {\n\t\t\tif lines[i] != \"\" {\n\t\t\t\t_, _ = fmt.Fprintln(&sanitized, token.Type(token.TYPE), quote(lines[i]))\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tsanitized.WriteRune('\\n')\n\t}\n\n\treturn sanitized.String()\n}\n\n// quote wraps a string in (single or double) quotes.\nfunc quote(s string) string {\n\tif strings.ContainsRune(s, '\"') && strings.ContainsRune(s, '\\'') {\n\t\treturn fmt.Sprintf(\"`%s`\", s)\n\t}\n\tif strings.ContainsRune(s, '\"') {\n\t\treturn fmt.Sprintf(`'%s'`, s)\n\t}\n\treturn fmt.Sprintf(`\"%s\"`, s)\n}\n"
  },
  {
    "path": "record_test.go",
    "content": "package main\n\nimport (\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestInputToTape(t *testing.T) {\n\ttests := []struct {\n\t\tname  string\n\t\tinput string\n\t\twant  string\n\t}{\n\t\t{\n\t\t\tname: \"ctrl key combinations\",\n\t\t\tinput: `echo \"Hello,.\nBACKSPACE\nLEFT\nLEFT\nRIGHT\nRIGHT\n world\"\nENTER\nENTER\nENTER\nls\nENTER\nENTER\nBACKSPACE\nCTRL+C\nCTRL+C\nCTRL+C\nCTRL+W\nCTRL+A\nCTRL+E\nSLEEP\nSLEEP\nALT+.\nSLEEP\nexit\n`,\n\t\t\twant: `Type 'echo \"Hello,.'\nBackspace\nLeft 2\nRight 2\nType ' world\"'\nEnter 3\nType \"ls\"\nEnter 2\nBackspace\nCtrl+C\nCtrl+C\nCtrl+C\nCtrl+W\nCtrl+A\nCtrl+E\nSleep 1s\nAlt+.\nSleep 500ms\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"PageUp, PageDown #559\",\n\t\t\tinput: `echo \"Hello,.\nPAGE_UP\nPAGE_UP\nPAGE_UP\nPAGE_UP\nPAGE_UP\nPAGE_UP\nPAGE_UP\nPAGE_UP\nPAGE_DOWN\nPAGE_DOWN\nPAGE_DOWN\nPAGE_DOWN\nexit\n`,\n\t\t\twant: `Type 'echo \"Hello,.'\nPageUp 8\nPageDown 4\n`,\n\t\t},\n\t}\n\tfor _, tc := range tests {\n\t\tgot := inputToTape(tc.input)\n\t\tif tc.want != got {\n\t\t\tt.Fatalf(\"want:\\n%s\\ngot:\\n%s\\n\", tc.want, got)\n\t\t}\n\t}\n}\n\nfunc TestInputToTapeLongSleep(t *testing.T) {\n\tinput := strings.Repeat(\"SLEEP\\n\", 121) + \"exit\"\n\twant := \"Sleep 60.5s\\n\"\n\tgot := inputToTape(input)\n\tif want != got {\n\t\tt.Fatalf(\"want:\\n%s\\ngot:\\n%s\\n\", want, got)\n\t}\n}\n\nfunc TestInputToTape_RepeatedSleepAfterExit(t *testing.T) {\n\tinput := \"SLEEP\\nexit\\nSLEEP\\nSLEEP\"\n\twant := \"Sleep 500ms\\nType \\\"exit\\\"\\nSleep 1s\\n\"\n\tgot := inputToTape(input)\n\tif want != got {\n\t\tt.Fatalf(\"want:\\n%s\\ngot:\\n%s\\n\", want, got)\n\t}\n}\n"
  },
  {
    "path": "screenshot.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"path/filepath\"\n)\n\n// ScreenshotOptions holds options related with screenshots.\ntype ScreenshotOptions struct {\n\t// frameCapture holds a flag indicating if screenshots must be taken.\n\tframeCapture bool\n\n\t// nextScreenshotPath holds the path of new screenshot.\n\tnextScreenshotPath string\n\n\t// screenshots represents a map holding screenshot path as key and frame as value.\n\tscreenshots map[string]int\n\n\t// Input represents location of cursor and text frames png files.\n\tinput string\n\n\tstyle *StyleOptions\n}\n\n// NewScreenshotOptions returns ScreenshotOptions by given input.\nfunc NewScreenshotOptions(input string, style *StyleOptions) ScreenshotOptions {\n\treturn ScreenshotOptions{\n\t\tframeCapture:       false,\n\t\tnextScreenshotPath: \"\",\n\t\tscreenshots:        make(map[string]int),\n\t\tinput:              input,\n\t\tstyle:              style,\n\t}\n}\n\n// makeScreenshot stores in screenshots map the target frame of the screenshot.\n// After storing frame it disables frame capture.\nfunc (opts *ScreenshotOptions) makeScreenshot(frame int) {\n\topts.screenshots[opts.nextScreenshotPath] = frame\n\n\topts.frameCapture = false\n\topts.nextScreenshotPath = \"\"\n}\n\n// captureNextFrame prepares capture of next frame by given path.\nfunc (opts *ScreenshotOptions) enableFrameCapture(path string) {\n\topts.frameCapture = true\n\topts.nextScreenshotPath = path\n}\n\n// MakeScreenshots generates screenshots by given ScreenshotOptions.\nfunc MakeScreenshots(opts ScreenshotOptions) []*exec.Cmd {\n\tcmds := []*exec.Cmd{} //nolint:prealloc\n\n\tfor path, frame := range opts.screenshots {\n\t\tcursorStream := filepath.Join(opts.input, fmt.Sprintf(cursorFrameFormat, frame))\n\t\ttextStream := filepath.Join(opts.input, fmt.Sprintf(textFrameFormat, frame))\n\n\t\targs := opts.buildFFopts(path, textStream, cursorStream)\n\n\t\tcmds = append(cmds, exec.Command(\n\t\t\t\"ffmpeg\",\n\t\t\targs...,\n\t\t))\n\t}\n\n\treturn cmds\n}\n\n// buildFFopts assembles an ffmpeg command from some VideoOptions.\nfunc (opts *ScreenshotOptions) buildFFopts(targetFile, textStream, cursorStream string) []string {\n\tvar args []string //nolint:prealloc\n\tstreamCounter := 2\n\n\tstreamBuilder := NewStreamBuilder(streamCounter, opts.input, opts.style)\n\t// Input frame options, used no matter what\n\t// Stream 0: text frames\n\t// Stream 1: cursor frames\n\tstreamBuilder.args = append(streamBuilder.args,\n\t\t\"-y\",\n\t\t\"-i\", textStream,\n\t\t\"-i\", cursorStream,\n\t)\n\n\tstreamBuilder = streamBuilder.\n\t\tWithMargin().\n\t\tWithBar().\n\t\tWithCorner()\n\n\tfilterBuilder := NewScreenshotFilterComplexBuilder(opts.style).\n\t\tWithWindowBar(streamBuilder.barStream).\n\t\tWithBorderRadius(streamBuilder.cornerStream).\n\t\tWithMarginFill(streamBuilder.marginStream)\n\n\targs = append(args, streamBuilder.Build()...)\n\targs = append(args, filterBuilder.Build()...)\n\targs = append(args, targetFile)\n\n\treturn args\n}\n"
  },
  {
    "path": "screenshot_test.go",
    "content": "package main\n\nimport \"testing\"\n\nfunc TestScreenshot(t *testing.T) {\n\tt.Run(\"makeScreenshot should add screenshot to map and disable capture\", func(t *testing.T) {\n\t\tpath := \"sample.png\"\n\t\ttargetFrame := 60\n\t\topts := ScreenshotOptions{\n\t\t\tnextScreenshotPath: path,\n\t\t\tframeCapture:       true,\n\t\t\tscreenshots:        make(map[string]int),\n\t\t}\n\n\t\topts.makeScreenshot(targetFrame)\n\n\t\tframe, ok := opts.screenshots[path]\n\t\tif !ok {\n\t\t\tt.Errorf(\"Unable to create screenshot: %s\", path)\n\t\t}\n\n\t\tif frame != targetFrame {\n\t\t\tt.Errorf(\"Unable to create screenshot: %s\", path)\n\t\t}\n\n\t\tif opts.frameCapture {\n\t\t\tt.Error(\"frameCapture should be false after invoking makeScreenshot\")\n\t\t}\n\t})\n\n\tt.Run(\"enableFrameCapture\", func(t *testing.T) {\n\t\tpath := \"sample.png\"\n\n\t\topts := ScreenshotOptions{\n\t\t\tframeCapture: false,\n\t\t}\n\n\t\topts.enableFrameCapture(path)\n\n\t\tif !opts.frameCapture {\n\t\t\tt.Error(\"frameCapture should be true after invoking enableFrameCapture\")\n\t\t}\n\n\t\tif opts.nextScreenshotPath != path {\n\t\t\tt.Errorf(\"nextScreenshotPath: %s, expected: %s\", opts.nextScreenshotPath, path)\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "scripts/download_theme.sh",
    "content": "#!/bin/sh\n\ncurl $1 |\n\tsed  \\\n\t\t-e 's/\"purple\":/\"magenta\":/g' \\\n\t\t-e 's/\"brightPurple\":/\"brightMagenta\":/g' \\\n\t\t-e 's/selectionBackground/selection/g' \\\n\t\t-e 's/cursorColor/cursor/g' |\n\tjq >$2.json\n"
  },
  {
    "path": "serve.go",
    "content": "package main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/caarlos0/env/v11\"\n\t\"github.com/charmbracelet/ssh\"\n\t\"github.com/charmbracelet/wish\"\n\t\"github.com/charmbracelet/wish/logging\"\n\t\"github.com/spf13/cobra\"\n)\n\nconst (\n\tmaxNumber = 1000000000\n\ttimeout   = 30 * time.Second\n)\n\ntype config struct {\n\tPort               int    `env:\"PORT\" envDefault:\"1976\"`\n\tHost               string `env:\"HOST\" envDefault:\"localhost\"`\n\tGID                int    `env:\"GID\" envDefault:\"0\"`\n\tUID                int    `env:\"UID\" envDefault:\"0\"`\n\tKeyPath            string `env:\"KEY_PATH\" envDefault:\"\"`\n\tAuthorizedKeysPath string `env:\"AUTHORIZED_KEYS_PATH\"`\n}\n\n//nolint:wrapcheck\nvar serveCmd = &cobra.Command{\n\tUse:   \"serve\",\n\tShort: \"Start the VHS SSH server\",\n\tRunE: func(cmd *cobra.Command, _ []string) error {\n\t\tvar cfg config\n\t\tif err := env.ParseWithOptions(&cfg, env.Options{\n\t\t\tPrefix: \"VHS_\",\n\t\t}); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tkey := cfg.KeyPath\n\t\tif key == \"\" {\n\t\t\tkey = filepath.Join(\".ssh\", \"vhs_ed25519\")\n\t\t}\n\t\taddr := net.JoinHostPort(cfg.Host, strconv.Itoa(cfg.Port))\n\t\ts, err := wish.NewServer(\n\t\t\twish.WithAddress(addr),\n\t\t\twish.WithHostKeyPath(key),\n\t\t\tfunc(s *ssh.Server) error {\n\t\t\t\tif cfg.AuthorizedKeysPath == \"\" {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\treturn wish.WithAuthorizedKeys(cfg.AuthorizedKeysPath)(s)\n\t\t\t},\n\t\t\twish.WithMiddleware(\n\t\t\t\tfunc(h ssh.Handler) ssh.Handler {\n\t\t\t\t\treturn func(s ssh.Session) {\n\t\t\t\t\t\t// Request for vhs must be passed in through stdin, which\n\t\t\t\t\t\t// implies that there is no PTY.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// In the future, we should support PTY by providing a\n\t\t\t\t\t\t// Bubble Tea interface for VHS.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// Ideally, users can SSH into the server and get a\n\t\t\t\t\t\t// walk through of how to write a .tape file.\n\t\t\t\t\t\t_, _, isPty := s.Pty()\n\t\t\t\t\t\tif isPty {\n\t\t\t\t\t\t\twish.Println(s, \"PTY is not supported\")\n\t\t\t\t\t\t\t_ = s.Exit(1)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read stdin passed from the client.\n\t\t\t\t\t\t// This is the .tape file which contains the VHS commands.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// ssh vhs.charm.sh < demo.tape\n\t\t\t\t\t\tvar b bytes.Buffer\n\t\t\t\t\t\t_, err := io.Copy(&b, s)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\twish.Errorln(s, err)\n\t\t\t\t\t\t\t_ = s.Exit(1)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//nolint:gosec\n\t\t\t\t\t\trand := rand.Int63n(maxNumber)\n\t\t\t\t\t\ttempFile := filepath.Join(os.TempDir(), fmt.Sprintf(\"vhs-%d\", rand))\n\t\t\t\t\t\tdefer func() { _ = os.Remove(tempFile) }()\n\t\t\t\t\t\terrs := Evaluate(s.Context(), b.String(), s.Stderr(), func(v *VHS) {\n\t\t\t\t\t\t\tvar gifOutput, mp4Output, webmOutput string\n\t\t\t\t\t\t\tswitch {\n\t\t\t\t\t\t\tcase v.Options.Video.Output.MP4 != \"\":\n\t\t\t\t\t\t\t\ttempFile += mp4\n\t\t\t\t\t\t\t\tmp4Output = tempFile\n\t\t\t\t\t\t\tcase v.Options.Video.Output.WebM != \"\":\n\t\t\t\t\t\t\t\ttempFile += webm\n\t\t\t\t\t\t\t\twebmOutput = tempFile\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\ttempFile += gif\n\t\t\t\t\t\t\t\tgifOutput = tempFile\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tv.Options.Video.Output.GIF = gifOutput\n\t\t\t\t\t\t\tv.Options.Video.Output.MP4 = mp4Output\n\t\t\t\t\t\t\tv.Options.Video.Output.WebM = webmOutput\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif len(errs) > 0 {\n\t\t\t\t\t\t\tprintErrors(s.Stderr(), b.String(), errs)\n\t\t\t\t\t\t\t_ = s.Exit(1)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tgif, _ := os.ReadFile(tempFile)\n\t\t\t\t\t\twish.Print(s, string(gif))\n\n\t\t\t\t\t\th(s)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tlogging.Middleware(),\n\t\t\t),\n\t\t)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// listen\n\t\tlog.Printf(\"Starting SSH server on %s\", addr)\n\t\tls, err := net.Listen(\"tcp\", addr)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to listen on %s: %w\", addr, err)\n\t\t}\n\n\t\t// drop privileges\n\t\tgid, uid := cfg.GID, cfg.UID\n\t\tif gid != 0 && uid != 0 {\n\t\t\tlog.Printf(\"Starting server with GID: %d, UID: %d\", gid, uid)\n\t\t\tif err := dropUserPrivileges(gid, uid); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tsch := make(chan error)\n\t\tgo func() {\n\t\t\tdefer close(sch)\n\t\t\tsch <- s.Serve(ls)\n\t\t}()\n\n\t\t<-cmd.Context().Done()\n\t\tlog.Println(\"Stopping SSH server\")\n\t\tctx, cancel := context.WithTimeout(context.Background(), timeout)\n\t\tdefer cancel()\n\t\tif err := s.Shutdown(ctx); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// wait for serve to finish\n\t\treturn <-sch\n\t},\n}\n"
  },
  {
    "path": "serve_unix.go",
    "content": "//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris\n// +build darwin dragonfly freebsd linux netbsd openbsd solaris\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"syscall\"\n)\n\nfunc dropUserPrivileges(gid int, uid int) error {\n\tif err := syscall.Setgid(gid); err != nil {\n\t\treturn fmt.Errorf(\"setgid error: %s\", err)\n\t}\n\tif err := syscall.Setuid(uid); err != nil {\n\t\treturn fmt.Errorf(\"setuid error: %s\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "serve_windows.go",
    "content": "//go:build windows\n// +build windows\n\npackage main\n\n// Windows doesn't support UID and GID, so we need to skip this.\nfunc dropUserPrivileges(int, int) error {\n\treturn nil\n}\n"
  },
  {
    "path": "shell.go",
    "content": "package main\n\n// Supported shells of VH.\nconst (\n\tbash       = \"bash\"\n\tcmdexe     = \"cmd\"\n\tfish       = \"fish\"\n\tnushell    = \"nu\"\n\tosh        = \"osh\"\n\tpowershell = \"powershell\"\n\tpwsh       = \"pwsh\"\n\txonsh      = \"xonsh\"\n\tzsh        = \"zsh\"\n)\n\n// Shell is a type that contains a prompt and the command to set up the shell.\ntype Shell struct {\n\tCommand []string\n\tEnv     []string\n}\n\n// Shells contains a mapping from shell names to their Shell struct.\nvar Shells = map[string]Shell{\n\tbash: {\n\t\tEnv:     []string{\"PS1=\\\\[\\\\e[38;2;90;86;224m\\\\]> \\\\[\\\\e[0m\\\\]\", \"BASH_SILENCE_DEPRECATION_WARNING=1\"},\n\t\tCommand: []string{\"bash\", \"--noprofile\", \"--norc\", \"--login\", \"+o\", \"history\"},\n\t},\n\tzsh: {\n\t\tEnv:     []string{`PROMPT=%F{#5B56E0}> %F{reset_color}`},\n\t\tCommand: []string{\"zsh\", \"--histnostore\", \"--no-rcs\"},\n\t},\n\tfish: {\n\t\tCommand: []string{\n\t\t\t\"fish\",\n\t\t\t\"--login\",\n\t\t\t\"--no-config\",\n\t\t\t\"--private\",\n\t\t\t\"-C\", \"function fish_greeting; end\",\n\t\t\t\"-C\", `function fish_prompt; set_color 5B56E0; echo -n \"> \"; set_color normal; end`,\n\t\t},\n\t},\n\tpowershell: {\n\t\tCommand: []string{\n\t\t\t\"powershell\",\n\t\t\t\"-NoLogo\",\n\t\t\t\"-NoExit\",\n\t\t\t\"-NoProfile\",\n\t\t\t\"-Command\",\n\t\t\t`Set-PSReadLineOption -HistorySaveStyle SaveNothing; function prompt { Write-Host '>' -NoNewLine -ForegroundColor Blue; return ' ' }`,\n\t\t},\n\t},\n\tpwsh: {\n\t\tCommand: []string{\n\t\t\t\"pwsh\",\n\t\t\t\"-Login\",\n\t\t\t\"-NoLogo\",\n\t\t\t\"-NoExit\",\n\t\t\t\"-NoProfile\",\n\t\t\t\"-Command\",\n\t\t\t`Set-PSReadLineOption -HistorySaveStyle SaveNothing; Function prompt { Write-Host -ForegroundColor Blue -NoNewLine '>'; return ' ' }`,\n\t\t},\n\t},\n\tcmdexe: {\n\t\tCommand: []string{\"cmd.exe\", \"/k\", \"prompt=^> \"},\n\t},\n\tnushell: {\n\t\tCommand: []string{\"nu\", \"--execute\", \"$env.PROMPT_COMMAND = {'\\033[;38;2;91;86;224m>\\033[m '}; $env.PROMPT_COMMAND_RIGHT = {''}\"},\n\t},\n\tosh: {\n\t\tEnv:     []string{\"PS1=\\\\[\\\\e[38;2;90;86;224m\\\\]> \\\\[\\\\e[0m\\\\]\"},\n\t\tCommand: []string{\"osh\", \"--norc\"},\n\t},\n\txonsh: {\n\t\tCommand: []string{\"xonsh\", \"--no-rc\", \"-D\", \"PROMPT=\\033[;38;2;91;86;224m>\\033[m \"},\n\t},\n}\n"
  },
  {
    "path": "style.go",
    "content": "package main\n\nimport (\n\t\"github.com/charmbracelet/lipgloss\"\n)\n\n// Theme colors.\nconst (\n\tBackground    = \"#171717\"\n\tForeground    = \"#dddddd\"\n\tBlack         = \"#282a2e\" // ansi 0\n\tBrightBlack   = \"#4d4d4d\" // ansi 8\n\tRed           = \"#D74E6F\" // ansi 1\n\tBrightRed     = \"#FE5F86\" // ansi 9\n\tGreen         = \"#31BB71\" // ansi 2\n\tBrightGreen   = \"#00D787\" // ansi 10\n\tYellow        = \"#D3E561\" // ansi 3\n\tBrightYellow  = \"#EBFF71\" // ansi 11\n\tBlue          = \"#8056FF\" // ansi 4\n\tBrightBlue    = \"#9B79FF\" // ansi 12\n\tMagenta       = \"#ED61D7\" // ansi 5\n\tBrightMagenta = \"#FF7AEA\" // ansi 13\n\tCyan          = \"#04D7D7\" // ansi 6\n\tBrightCyan    = \"#00FEFE\" // ansi 14\n\tWhite         = \"#bfbfbf\" // ansi 7\n\tBrightWhite   = \"#e6e6e6\" // ansi 15\n\tIndigo        = \"#5B56E0\"\n)\n\nconst (\n\tdefaultColumns       = 80\n\tdefaultHeight        = 600\n\tdefaultMaxColors     = 256\n\tdefaultPadding       = 60\n\tdefaultWindowBarSize = 30\n\tdefaultPlaybackSpeed = 1.0\n\tdefaultWidth         = 1200\n)\n\n// Styles for syntax highlightin.\nvar (\n\tCommandStyle    = lipgloss.NewStyle().Foreground(lipgloss.Color(\"12\"))\n\tFaintStyle      = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: \"242\", Dark: \"238\"})\n\tNoneStyle       = lipgloss.NewStyle()\n\tKeywordStyle    = lipgloss.NewStyle()\n\tURLStyle        = lipgloss.NewStyle().Foreground(lipgloss.Color(\"3\"))\n\tNumberStyle     = lipgloss.NewStyle().Foreground(lipgloss.Color(\"3\"))\n\tStringStyle     = lipgloss.NewStyle().Foreground(lipgloss.Color(\"10\"))\n\tTimeStyle       = lipgloss.NewStyle().Foreground(lipgloss.Color(\"11\"))\n\tLineNumberStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(\"8\"))\n\tErrorStyle      = lipgloss.NewStyle().Foreground(lipgloss.Color(\"1\"))\n\tGrayStyle       = lipgloss.NewStyle().Foreground(lipgloss.Color(\"8\"))\n\tErrorFileStyle  = lipgloss.NewStyle().\n\t\t\tBorder(lipgloss.NormalBorder()).\n\t\t\tBorderForeground(lipgloss.Color(\"8\")).\n\t\t\tForeground(lipgloss.Color(\"1\")).\n\t\t\tPadding(0, 1).\n\t\t\tWidth(defaultColumns)\n)\n\n// StyleOptions represents the ui options for video and screenshots.\ntype StyleOptions struct {\n\tWidth           int\n\tHeight          int\n\tPadding         int\n\tBackgroundColor string\n\tMarginFill      string\n\tMargin          int\n\tWindowBar       string\n\tWindowBarSize   int\n\tWindowBarColor  string\n\tBorderRadius    int\n}\n\n// DefaultStyleOptions returns default Style config.\nfunc DefaultStyleOptions() *StyleOptions {\n\treturn &StyleOptions{\n\t\tWidth:           defaultWidth,\n\t\tHeight:          defaultHeight,\n\t\tPadding:         defaultPadding,\n\t\tMarginFill:      DefaultTheme.Background,\n\t\tMargin:          0,\n\t\tWindowBar:       \"\",\n\t\tWindowBarSize:   defaultWindowBarSize,\n\t\tWindowBarColor:  DefaultTheme.Background,\n\t\tBorderRadius:    0,\n\t\tBackgroundColor: DefaultTheme.Background,\n\t}\n}\n"
  },
  {
    "path": "syntax.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/vhs/parser\"\n\t\"github.com/charmbracelet/vhs/token\"\n\t\"github.com/mattn/go-runewidth\"\n)\n\nconst sourceDisplayMaxLength = 10\n\n// Highlight syntax highlights a command for prettier printing.\n// It takes an argument whether or not to print the command in a faint style to\n// represent hidden commands.\nfunc Highlight(c parser.Command, faint bool) string {\n\tvar (\n\t\toptionsStyle = TimeStyle\n\t\targsStyle    = NumberStyle\n\t)\n\n\tsourcePrefix := \"\"\n\tif c.Source != \"\" {\n\t\tdisplayPath := runewidth.Truncate(strings.TrimSuffix(c.Source, extension), sourceDisplayMaxLength, \"…\")\n\t\tsourcePrefix = GrayStyle.Render(displayPath+\":\") + \" \"\n\t}\n\n\tif faint {\n\t\tif c.Options != \"\" {\n\t\t\treturn sourcePrefix + FaintStyle.Render(fmt.Sprintf(\"%s %s %s\", c.Type, c.Options, c.Args))\n\t\t}\n\t\treturn sourcePrefix + FaintStyle.Render(fmt.Sprintf(\"%s %s\", c.Type, c.Args))\n\t}\n\n\tswitch c.Type {\n\tcase token.REGEX:\n\t\targsStyle = StringStyle\n\tcase token.SET:\n\t\toptionsStyle = KeywordStyle\n\t\tif isNumber(c.Args) {\n\t\t\targsStyle = NumberStyle\n\t\t} else if isTime(c.Args) {\n\t\t\targsStyle = TimeStyle\n\t\t} else {\n\t\t\targsStyle = StringStyle\n\t\t}\n\tcase token.ENV:\n\t\toptionsStyle = NoneStyle\n\t\targsStyle = StringStyle\n\tcase token.OUTPUT:\n\t\toptionsStyle = NoneStyle\n\t\targsStyle = StringStyle\n\tcase token.CTRL:\n\t\targsStyle = CommandStyle\n\tcase token.SLEEP:\n\t\targsStyle = TimeStyle\n\tcase token.TYPE:\n\t\toptionsStyle = TimeStyle\n\t\targsStyle = StringStyle\n\tcase token.HIDE, token.SHOW:\n\t\treturn FaintStyle.Render(c.Type.String())\n\t}\n\n\tvar s strings.Builder\n\ts.WriteString(sourcePrefix)\n\ts.WriteString(CommandStyle.Render(c.Type.String()) + \" \")\n\tif c.Options != \"\" {\n\t\ts.WriteString(optionsStyle.Render(c.Options))\n\t\tswitch c.Type {\n\t\tcase token.ENV:\n\t\t\ts.WriteString(\"=\")\n\t\tdefault:\n\t\t\ts.WriteString(\" \")\n\t\t}\n\t}\n\ts.WriteString(argsStyle.Render(c.Args))\n\treturn s.String()\n}\n\nvar numberRegex = regexp.MustCompile(\"^[0-9]+$\")\n\nfunc isNumber(s string) bool {\n\treturn numberRegex.MatchString(s)\n}\n\nvar timeRegex = regexp.MustCompile(\"^[0-9]+m?s$\")\n\nfunc isTime(s string) bool {\n\treturn timeRegex.MatchString(s)\n}\n"
  },
  {
    "path": "testing.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n)\n\n// TestOptions is the set of options for the testing functionality.\ntype TestOptions struct {\n\tOutput string\n\tGolden string\n}\n\n// DefaultTestOptions returns the default set of options for the testing functionality.\nfunc DefaultTestOptions() TestOptions {\n\treturn TestOptions{\n\t\tOutput: \"out.test\",\n\t}\n}\n\n// Alternatively, `var separator = strings.Repeat(\"─\", 80)`.\nconst separator = \"────────────────────────────────────────────────────────────────────────────────\"\n\nvar (\n\tonce sync.Once\n\tfile *os.File\n)\n\n// SaveOutput saves the current buffer to the output file.\nfunc (v *VHS) SaveOutput() error {\n\tvar err error\n\t// Create output file (once)\n\tonce.Do(func() {\n\t\terr = os.MkdirAll(filepath.Dir(v.Options.Test.Output), 0o750)\n\t\tif err != nil {\n\t\t\tfile, err = os.CreateTemp(os.TempDir(), \"vhs-*.txt\")\n\t\t\treturn\n\t\t}\n\t\tfile, err = os.Create(v.Options.Test.Output)\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create output file: %w\", err)\n\t}\n\n\tlines, err := v.Buffer()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get buffer: %w\", err)\n\t}\n\n\tfor _, line := range lines {\n\t\t_, err = file.WriteString(line + \"\\n\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to write buffer to file: %w\", err)\n\t\t}\n\t}\n\n\t_, err = file.WriteString(separator + \"\\n\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to write separator to file: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// Buffer returns the current buffer.\nfunc (v *VHS) Buffer() ([]string, error) {\n\t// Get the current buffer.\n\tbuf, err := v.Page.Eval(\"() => Array(term.rows).fill(0).map((e, i) => term.buffer.active.getLine(i).translateToString().trimEnd())\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read buffer: %w\", err)\n\t}\n\n\tarr := buf.Value.Arr()\n\tlines := make([]string, 0, len(arr))\n\tfor _, line := range arr {\n\t\tlines = append(lines, line.Str())\n\t}\n\n\treturn lines, nil\n}\n\n// CurrentLine returns the current line from the buffer.\nfunc (v *VHS) CurrentLine() (string, error) {\n\tbuf, err := v.Page.Eval(\"() => term.buffer.active.getLine(term.buffer.active.cursorY+term.buffer.active.viewportY).translateToString().trimEnd()\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"read current line from buffer: %w\", err)\n\t}\n\n\treturn buf.Value.Str(), nil\n}\n"
  },
  {
    "path": "themes.go",
    "content": "// Package main theme.go contains the information about a terminal theme.\n// It stores the 16 base colors as well as the background and foreground colors\n// of the terminal theme.\n//\n// It can be changed through the Set command.\n//\n// Set Theme {\"background\": \"#171717\"}\n// Set Theme \"Catppuccin Mocha\"\n//\n//go:generate make all\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/glamour/ansi\"\n\n\t_ \"embed\"\n\n\t\"github.com/agnivade/levenshtein\"\n)\n\n// Theme is a terminal theme for xterm.js\n// It is used for marshalling between the xterm.js readable json format and a\n// valid go struct.\n// https://xtermjs.org/docs/api/terminal/interfaces/itheme/\ntype Theme struct {\n\tName          string `json:\"name\"`\n\tBackground    string `json:\"background\"`\n\tForeground    string `json:\"foreground\"`\n\tSelection     string `json:\"selection\"`\n\tCursor        string `json:\"cursor\"`\n\tCursorAccent  string `json:\"cursorAccent\"`\n\tBlack         string `json:\"black\"`\n\tBrightBlack   string `json:\"brightBlack\"`\n\tRed           string `json:\"red\"`\n\tBrightRed     string `json:\"brightRed\"`\n\tGreen         string `json:\"green\"`\n\tBrightGreen   string `json:\"brightGreen\"`\n\tYellow        string `json:\"yellow\"`\n\tBrightYellow  string `json:\"brightYellow\"`\n\tBlue          string `json:\"blue\"`\n\tBrightBlue    string `json:\"brightBlue\"`\n\tMagenta       string `json:\"magenta\"`\n\tBrightMagenta string `json:\"brightMagenta\"`\n\tCyan          string `json:\"cyan\"`\n\tBrightCyan    string `json:\"brightCyan\"`\n\tWhite         string `json:\"white\"`\n\tBrightWhite   string `json:\"brightWhite\"`\n}\n\nfunc (t Theme) String() string {\n\tts, err := json.Marshal(t)\n\tif err != nil {\n\t\tdts, _ := json.Marshal(DefaultTheme)\n\t\treturn string(dts)\n\t}\n\treturn string(ts)\n}\n\n// DefaultTheme is the default theme to use for recording demos and\n// screenshots.\n//\n// Taken from https://github.com/meowgorithm/dotfiles.\nvar DefaultTheme = Theme{\n\tBackground:    Background,\n\tForeground:    Foreground,\n\tCursor:        Foreground,\n\tCursorAccent:  Background,\n\tBlack:         Black,\n\tBrightBlack:   BrightBlack,\n\tRed:           Red,\n\tBrightRed:     BrightRed,\n\tGreen:         Green,\n\tBrightGreen:   BrightGreen,\n\tYellow:        Yellow,\n\tBrightYellow:  BrightYellow,\n\tBlue:          Blue,\n\tBrightBlue:    BrightBlue,\n\tMagenta:       Magenta,\n\tBrightMagenta: BrightMagenta,\n\tCyan:          Cyan,\n\tBrightCyan:    BrightCyan,\n\tWhite:         White,\n\tBrightWhite:   BrightWhite,\n}\n\nconst margin = 2\n\n// GlamourTheme is the theme for printing out the manual page ('vhs man').\nvar GlamourTheme = ansi.StyleConfig{\n\tDocument: ansi.StyleBlock{\n\t\tStylePrimitive: ansi.StylePrimitive{\n\t\t\tBlockPrefix: \"\\n\",\n\t\t\tBlockSuffix: \"\\n\",\n\t\t},\n\t\tMargin: uintPtr(margin),\n\t},\n\tHeading: ansi.StyleBlock{\n\t\tStylePrimitive: ansi.StylePrimitive{\n\t\t\tBlockSuffix: \"\\n\",\n\t\t\tColor:       stringPtr(\"99\"),\n\t\t\tBold:        boolPtr(true),\n\t\t},\n\t},\n\tItem:     ansi.StylePrimitive{Prefix: \"· \"},\n\tEmph:     ansi.StylePrimitive{Color: stringPtr(BrightBlack)},\n\tStrong:   ansi.StylePrimitive{Bold: boolPtr(true)},\n\tLink:     ansi.StylePrimitive{Color: stringPtr(\"42\"), Underline: boolPtr(true)},\n\tLinkText: ansi.StylePrimitive{Color: stringPtr(\"207\")},\n\tCode:     ansi.StyleBlock{StylePrimitive: ansi.StylePrimitive{Color: stringPtr(\"204\")}},\n}\n\nfunc boolPtr(b bool) *bool       { return &b }\nfunc stringPtr(s string) *string { return &s }\nfunc uintPtr(u uint) *uint       { return &u }\n\n//go:embed themes.json\nvar themesBts []byte\n\n// ThemeNotFoundError is returned when a requested theme is not found.\ntype ThemeNotFoundError struct {\n\tTheme       string\n\tSuggestions []string\n}\n\nfunc (e ThemeNotFoundError) Error() string {\n\tif len(e.Suggestions) == 0 {\n\t\treturn fmt.Sprintf(\"invalid `Set Theme %q`: theme does not exist\", e.Theme)\n\t}\n\n\treturn fmt.Sprintf(\"invalid `Set Theme %q`: did you mean %q\",\n\t\te.Theme,\n\t\tstrings.Join(e.Suggestions, \", \"),\n\t)\n}\n\n// sortedThemeNames returns the names of the themes, sorted.\nfunc sortedThemeNames() ([]string, error) {\n\tvar keys []string\n\tfor _, bts := range [][]byte{themesBts} {\n\t\tthemes, err := parseThemes(bts)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tfor _, theme := range themes {\n\t\t\tkeys = append(keys, theme.Name)\n\t\t}\n\t}\n\tsort.Slice(keys, func(i, j int) bool {\n\t\treturn strings.ToLower(keys[i]) < strings.ToLower(keys[j])\n\t})\n\treturn keys, nil\n}\n\nconst distance = 2\n\n// findTheme return the given theme, if it exists.\nfunc findTheme(name string) (Theme, error) {\n\tfor _, bts := range [][]byte{themesBts} {\n\t\tthemes, err := parseThemes(bts)\n\t\tif err != nil {\n\t\t\treturn DefaultTheme, err\n\t\t}\n\n\t\tfor _, theme := range themes {\n\t\t\tif theme.Name == name {\n\t\t\t\treturn theme, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// not found, lets find similar themes!\n\tkeys, err := sortedThemeNames()\n\tif err != nil {\n\t\treturn DefaultTheme, err\n\t}\n\n\tsuggestions := []string{}\n\tlname := strings.ToLower(name)\n\tfor _, theme := range keys {\n\t\tltheme := strings.ToLower(theme)\n\t\tlevenshteinDistance := levenshtein.ComputeDistance(lname, ltheme)\n\t\tsuggestByLevenshtein := levenshteinDistance <= distance\n\t\tsuggestByPrefix := strings.HasPrefix(lname, ltheme)\n\t\tif suggestByLevenshtein || suggestByPrefix {\n\t\t\tsuggestions = append(suggestions, theme)\n\t\t}\n\t}\n\treturn DefaultTheme, ThemeNotFoundError{name, suggestions}\n}\n\nfunc parseThemes(bts []byte) ([]Theme, error) {\n\tvar themes []Theme\n\tif err := json.Unmarshal(bts, &themes); err != nil {\n\t\treturn nil, fmt.Errorf(\"could not load themes.json: %w\", err)\n\t}\n\treturn themes, nil\n}\n"
  },
  {
    "path": "themes.json",
    "content": "[\n  {\n    \"name\": \"3024 Day\",\n    \"black\": \"#090300\",\n    \"red\": \"#db2d20\",\n    \"green\": \"#01a252\",\n    \"yellow\": \"#fded02\",\n    \"blue\": \"#01a0e4\",\n    \"magenta\": \"#a16a94\",\n    \"cyan\": \"#b5e4f4\",\n    \"white\": \"#a5a2a2\",\n    \"brightBlack\": \"#5c5855\",\n    \"brightRed\": \"#e8bbd0\",\n    \"brightGreen\": \"#3a3432\",\n    \"brightYellow\": \"#4a4543\",\n    \"brightBlue\": \"#807d7c\",\n    \"brightMagenta\": \"#d6d5d4\",\n    \"brightCyan\": \"#cdab53\",\n    \"brightWhite\": \"#f7f7f7\",\n    \"background\": \"#f7f7f7\",\n    \"foreground\": \"#4a4543\",\n    \"cursor\": \"#4a4543\",\n    \"selection\": \"#a5a2a2\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"0x3024\",\n          \"link\": \"https://github.com/0x3024\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"3024 Night\",\n    \"black\": \"#090300\",\n    \"red\": \"#db2d20\",\n    \"green\": \"#01a252\",\n    \"yellow\": \"#fded02\",\n    \"blue\": \"#01a0e4\",\n    \"magenta\": \"#a16a94\",\n    \"cyan\": \"#b5e4f4\",\n    \"white\": \"#a5a2a2\",\n    \"brightBlack\": \"#5c5855\",\n    \"brightRed\": \"#e8bbd0\",\n    \"brightGreen\": \"#3a3432\",\n    \"brightYellow\": \"#4a4543\",\n    \"brightBlue\": \"#807d7c\",\n    \"brightMagenta\": \"#d6d5d4\",\n    \"brightCyan\": \"#cdab53\",\n    \"brightWhite\": \"#f7f7f7\",\n    \"background\": \"#090300\",\n    \"foreground\": \"#a5a2a2\",\n    \"cursor\": \"#a5a2a2\",\n    \"selection\": \"#4a4543\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"0x3024\",\n          \"link\": \"https://github.com/0x3024\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Aardvark Blue\",\n    \"black\": \"#191919\",\n    \"red\": \"#aa342e\",\n    \"green\": \"#4b8c0f\",\n    \"yellow\": \"#dbba00\",\n    \"blue\": \"#1370d3\",\n    \"magenta\": \"#c43ac3\",\n    \"cyan\": \"#008eb0\",\n    \"white\": \"#bebebe\",\n    \"brightBlack\": \"#454545\",\n    \"brightRed\": \"#f05b50\",\n    \"brightGreen\": \"#95dc55\",\n    \"brightYellow\": \"#ffe763\",\n    \"brightBlue\": \"#60a4ec\",\n    \"brightMagenta\": \"#e26be2\",\n    \"brightCyan\": \"#60b6cb\",\n    \"brightWhite\": \"#f7f7f7\",\n    \"background\": \"#102040\",\n    \"foreground\": \"#dddddd\",\n    \"cursor\": \"#007acc\",\n    \"selection\": \"#bfdbfe\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Abernathy\",\n    \"black\": \"#000000\",\n    \"red\": \"#cd0000\",\n    \"green\": \"#00cd00\",\n    \"yellow\": \"#cdcd00\",\n    \"blue\": \"#1093f5\",\n    \"magenta\": \"#cd00cd\",\n    \"cyan\": \"#00cdcd\",\n    \"white\": \"#faebd7\",\n    \"brightBlack\": \"#404040\",\n    \"brightRed\": \"#ff0000\",\n    \"brightGreen\": \"#00ff00\",\n    \"brightYellow\": \"#ffff00\",\n    \"brightBlue\": \"#11b5f6\",\n    \"brightMagenta\": \"#ff00ff\",\n    \"brightCyan\": \"#00ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#111416\",\n    \"foreground\": \"#eeeeec\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#eeeeec\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Adventure\",\n    \"black\": \"#040404\",\n    \"red\": \"#d84a33\",\n    \"green\": \"#5da602\",\n    \"yellow\": \"#eebb6e\",\n    \"blue\": \"#417ab3\",\n    \"magenta\": \"#e5c499\",\n    \"cyan\": \"#bdcfe5\",\n    \"white\": \"#dbded8\",\n    \"brightBlack\": \"#685656\",\n    \"brightRed\": \"#d76b42\",\n    \"brightGreen\": \"#99b52c\",\n    \"brightYellow\": \"#ffb670\",\n    \"brightBlue\": \"#97d7ef\",\n    \"brightMagenta\": \"#aa7900\",\n    \"brightCyan\": \"#bdcfe5\",\n    \"brightWhite\": \"#e4d5c7\",\n    \"background\": \"#040404\",\n    \"foreground\": \"#feffff\",\n    \"cursor\": \"#feffff\",\n    \"selection\": \"#606060\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"hongzimao\",\n          \"link\": \"https://github.com/hongzimao/iTerm2-Color-Schemes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"AdventureTime\",\n    \"black\": \"#050404\",\n    \"red\": \"#bd0013\",\n    \"green\": \"#4ab118\",\n    \"yellow\": \"#e7741e\",\n    \"blue\": \"#0f4ac6\",\n    \"magenta\": \"#665993\",\n    \"cyan\": \"#70a598\",\n    \"white\": \"#f8dcc0\",\n    \"brightBlack\": \"#4e7cbf\",\n    \"brightRed\": \"#fc5f5a\",\n    \"brightGreen\": \"#9eff6e\",\n    \"brightYellow\": \"#efc11a\",\n    \"brightBlue\": \"#1997c6\",\n    \"brightMagenta\": \"#9b5953\",\n    \"brightCyan\": \"#c8faf4\",\n    \"brightWhite\": \"#f6f5fb\",\n    \"background\": \"#1f1d45\",\n    \"foreground\": \"#f8dcc0\",\n    \"cursor\": \"#efbf38\",\n    \"selection\": \"#706b4e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Afterglow\",\n    \"black\": \"#151515\",\n    \"red\": \"#ac4142\",\n    \"green\": \"#7e8e50\",\n    \"yellow\": \"#e5b567\",\n    \"blue\": \"#6c99bb\",\n    \"magenta\": \"#9f4e85\",\n    \"cyan\": \"#7dd6cf\",\n    \"white\": \"#d0d0d0\",\n    \"brightBlack\": \"#505050\",\n    \"brightRed\": \"#ac4142\",\n    \"brightGreen\": \"#7e8e50\",\n    \"brightYellow\": \"#e5b567\",\n    \"brightBlue\": \"#6c99bb\",\n    \"brightMagenta\": \"#9f4e85\",\n    \"brightCyan\": \"#7dd6cf\",\n    \"brightWhite\": \"#f5f5f5\",\n    \"background\": \"#212121\",\n    \"foreground\": \"#d0d0d0\",\n    \"cursor\": \"#d0d0d0\",\n    \"selection\": \"#303030\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"yabatadesign\",\n          \"link\": \"https://github.com/YabataDesign/afterglow-itermcolors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Alabaster\",\n    \"black\": \"#000000\",\n    \"red\": \"#aa3731\",\n    \"green\": \"#448c27\",\n    \"yellow\": \"#cb9000\",\n    \"blue\": \"#325cc0\",\n    \"magenta\": \"#7a3e9d\",\n    \"cyan\": \"#0083b2\",\n    \"white\": \"#f7f7f7\",\n    \"brightBlack\": \"#777777\",\n    \"brightRed\": \"#f05050\",\n    \"brightGreen\": \"#60cb00\",\n    \"brightYellow\": \"#ffbc5d\",\n    \"brightBlue\": \"#007acc\",\n    \"brightMagenta\": \"#e64ce6\",\n    \"brightCyan\": \"#00aacb\",\n    \"brightWhite\": \"#f7f7f7\",\n    \"background\": \"#f7f7f7\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#007acc\",\n    \"selection\": \"#bfdbfe\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"AlienBlood\",\n    \"black\": \"#112616\",\n    \"red\": \"#7f2b27\",\n    \"green\": \"#2f7e25\",\n    \"yellow\": \"#717f24\",\n    \"blue\": \"#2f6a7f\",\n    \"magenta\": \"#47587f\",\n    \"cyan\": \"#327f77\",\n    \"white\": \"#647d75\",\n    \"brightBlack\": \"#3c4812\",\n    \"brightRed\": \"#e08009\",\n    \"brightGreen\": \"#18e000\",\n    \"brightYellow\": \"#bde000\",\n    \"brightBlue\": \"#00aae0\",\n    \"brightMagenta\": \"#0058e0\",\n    \"brightCyan\": \"#00e0c4\",\n    \"brightWhite\": \"#73fa91\",\n    \"background\": \"#0f1610\",\n    \"foreground\": \"#637d75\",\n    \"cursor\": \"#73fa91\",\n    \"selection\": \"#1d4125\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Andromeda\",\n    \"black\": \"#000000\",\n    \"red\": \"#cd3131\",\n    \"green\": \"#05bc79\",\n    \"yellow\": \"#e5e512\",\n    \"blue\": \"#2472c8\",\n    \"magenta\": \"#bc3fbc\",\n    \"cyan\": \"#0fa8cd\",\n    \"white\": \"#e5e5e5\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#cd3131\",\n    \"brightGreen\": \"#05bc79\",\n    \"brightYellow\": \"#e5e512\",\n    \"brightBlue\": \"#2472c8\",\n    \"brightMagenta\": \"#bc3fbc\",\n    \"brightCyan\": \"#0fa8cd\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#262a33\",\n    \"foreground\": \"#e5e5e5\",\n    \"cursor\": \"#f8f8f0\",\n    \"selection\": \"#5a5c62\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"memije\",\n          \"link\": \"https://github.com/memije\"\n        },\n        {\n          \"name\": \"EliverLara\",\n          \"link\": \"https://github.com/EliverLara/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Apple Classic\",\n    \"black\": \"#000000\",\n    \"red\": \"#c91b00\",\n    \"green\": \"#00c200\",\n    \"yellow\": \"#c7c400\",\n    \"blue\": \"#0225c7\",\n    \"magenta\": \"#ca30c7\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff6e67\",\n    \"brightGreen\": \"#5ffa68\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#ff77ff\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#2c2b2b\",\n    \"foreground\": \"#d5a200\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#6b5b02\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"arcoiris\",\n    \"black\": \"#333333\",\n    \"red\": \"#da2700\",\n    \"green\": \"#12c258\",\n    \"yellow\": \"#ffc656\",\n    \"blue\": \"#518bfc\",\n    \"magenta\": \"#e37bd9\",\n    \"cyan\": \"#63fad5\",\n    \"white\": \"#bab2b2\",\n    \"brightBlack\": \"#777777\",\n    \"brightRed\": \"#ffb9b9\",\n    \"brightGreen\": \"#e3f6aa\",\n    \"brightYellow\": \"#ffddaa\",\n    \"brightBlue\": \"#b3e8f3\",\n    \"brightMagenta\": \"#cbbaf9\",\n    \"brightCyan\": \"#bcffc7\",\n    \"brightWhite\": \"#efefef\",\n    \"background\": \"#201f1e\",\n    \"foreground\": \"#eee4d9\",\n    \"cursor\": \"#7a1c1c\",\n    \"selection\": \"#25524a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Argonaut\",\n    \"black\": \"#232323\",\n    \"red\": \"#ff000f\",\n    \"green\": \"#8ce10b\",\n    \"yellow\": \"#ffb900\",\n    \"blue\": \"#008df8\",\n    \"magenta\": \"#6d43a6\",\n    \"cyan\": \"#00d8eb\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#444444\",\n    \"brightRed\": \"#ff2740\",\n    \"brightGreen\": \"#abe15b\",\n    \"brightYellow\": \"#ffd242\",\n    \"brightBlue\": \"#0092ff\",\n    \"brightMagenta\": \"#9a5feb\",\n    \"brightCyan\": \"#67fff0\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0e1019\",\n    \"foreground\": \"#fffaf4\",\n    \"cursor\": \"#ff0018\",\n    \"selection\": \"#002a3b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"effkay\",\n          \"link\": \"https://github.com/effkay/iTerm-argonaut\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Arthur\",\n    \"black\": \"#3d352a\",\n    \"red\": \"#cd5c5c\",\n    \"green\": \"#86af80\",\n    \"yellow\": \"#e8ae5b\",\n    \"blue\": \"#6495ed\",\n    \"magenta\": \"#deb887\",\n    \"cyan\": \"#b0c4de\",\n    \"white\": \"#bbaa99\",\n    \"brightBlack\": \"#554444\",\n    \"brightRed\": \"#cc5533\",\n    \"brightGreen\": \"#88aa22\",\n    \"brightYellow\": \"#ffa75d\",\n    \"brightBlue\": \"#87ceeb\",\n    \"brightMagenta\": \"#996600\",\n    \"brightCyan\": \"#b0c4de\",\n    \"brightWhite\": \"#ddccbb\",\n    \"background\": \"#1c1c1c\",\n    \"foreground\": \"#ddeedd\",\n    \"cursor\": \"#e2bbef\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"baskerville\",\n          \"link\": \"https://github.com/baskerville/iTerm-2-Color-Themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"AtelierSulphurpool\",\n    \"black\": \"#202746\",\n    \"red\": \"#c94922\",\n    \"green\": \"#ac9739\",\n    \"yellow\": \"#c08b30\",\n    \"blue\": \"#3d8fd1\",\n    \"magenta\": \"#6679cc\",\n    \"cyan\": \"#22a2c9\",\n    \"white\": \"#979db4\",\n    \"brightBlack\": \"#6b7394\",\n    \"brightRed\": \"#c76b29\",\n    \"brightGreen\": \"#293256\",\n    \"brightYellow\": \"#5e6687\",\n    \"brightBlue\": \"#898ea4\",\n    \"brightMagenta\": \"#dfe2f1\",\n    \"brightCyan\": \"#9c637a\",\n    \"brightWhite\": \"#f5f7ff\",\n    \"background\": \"#202746\",\n    \"foreground\": \"#979db4\",\n    \"cursor\": \"#979db4\",\n    \"selection\": \"#5e6687\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"atelierbram\",\n          \"link\": \"http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Atom\",\n    \"black\": \"#000000\",\n    \"red\": \"#fd5ff1\",\n    \"green\": \"#87c38a\",\n    \"yellow\": \"#ffd7b1\",\n    \"blue\": \"#85befd\",\n    \"magenta\": \"#b9b6fc\",\n    \"cyan\": \"#85befd\",\n    \"white\": \"#e0e0e0\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#fd5ff1\",\n    \"brightGreen\": \"#94fa36\",\n    \"brightYellow\": \"#f5ffa8\",\n    \"brightBlue\": \"#96cbfe\",\n    \"brightMagenta\": \"#b9b6fc\",\n    \"brightCyan\": \"#85befd\",\n    \"brightWhite\": \"#e0e0e0\",\n    \"background\": \"#161719\",\n    \"foreground\": \"#c5c8c6\",\n    \"cursor\": \"#d0d0d0\",\n    \"selection\": \"#444444\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"bahlo\",\n          \"link\": \"https://github.com/bahlo/iterm-colors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"AtomOneLight\",\n    \"black\": \"#000000\",\n    \"red\": \"#de3e35\",\n    \"green\": \"#3f953a\",\n    \"yellow\": \"#d2b67c\",\n    \"blue\": \"#2f5af3\",\n    \"magenta\": \"#950095\",\n    \"cyan\": \"#3f953a\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#de3e35\",\n    \"brightGreen\": \"#3f953a\",\n    \"brightYellow\": \"#d2b67c\",\n    \"brightBlue\": \"#2f5af3\",\n    \"brightMagenta\": \"#a00095\",\n    \"brightCyan\": \"#3f953a\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#f9f9f9\",\n    \"foreground\": \"#2a2c33\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#ededed\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"iamstarkov\",\n          \"link\": \"https://github.com/iamstarkov\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Aurora\",\n    \"black\": \"#23262e\",\n    \"red\": \"#f0266f\",\n    \"green\": \"#8fd46d\",\n    \"yellow\": \"#ffe66d\",\n    \"blue\": \"#0321d7\",\n    \"magenta\": \"#ee5d43\",\n    \"cyan\": \"#03d6b8\",\n    \"white\": \"#c74ded\",\n    \"brightBlack\": \"#292e38\",\n    \"brightRed\": \"#f92672\",\n    \"brightGreen\": \"#8fd46d\",\n    \"brightYellow\": \"#ffe66d\",\n    \"brightBlue\": \"#03d6b8\",\n    \"brightMagenta\": \"#ee5d43\",\n    \"brightCyan\": \"#03d6b8\",\n    \"brightWhite\": \"#c74ded\",\n    \"background\": \"#23262e\",\n    \"foreground\": \"#ffca28\",\n    \"cursor\": \"#ee5d43\",\n    \"selection\": \"#292e38\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"fcsmJS\",\n          \"link\": \"https://github.com/fcsmJS/iTerm2-Color-Schemes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"ayu\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff3333\",\n    \"green\": \"#b8cc52\",\n    \"yellow\": \"#e7c547\",\n    \"blue\": \"#36a3d9\",\n    \"magenta\": \"#f07178\",\n    \"cyan\": \"#95e6cb\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#ff6565\",\n    \"brightGreen\": \"#eafe84\",\n    \"brightYellow\": \"#fff779\",\n    \"brightBlue\": \"#68d5ff\",\n    \"brightMagenta\": \"#ffa3aa\",\n    \"brightCyan\": \"#c7fffd\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0f1419\",\n    \"foreground\": \"#e6e1cf\",\n    \"cursor\": \"#f29718\",\n    \"selection\": \"#253340\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"alebcay\",\n          \"link\": \"https://github.com/alebcay\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Ayu Mirage\",\n    \"black\": \"#191e2a\",\n    \"red\": \"#ed8274\",\n    \"green\": \"#a6cc70\",\n    \"yellow\": \"#fad07b\",\n    \"blue\": \"#6dcbfa\",\n    \"magenta\": \"#cfbafa\",\n    \"cyan\": \"#90e1c6\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#f28779\",\n    \"brightGreen\": \"#bae67e\",\n    \"brightYellow\": \"#ffd580\",\n    \"brightBlue\": \"#73d0ff\",\n    \"brightMagenta\": \"#d4bfff\",\n    \"brightCyan\": \"#95e6cb\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1f2430\",\n    \"foreground\": \"#cbccc6\",\n    \"cursor\": \"#ffcc66\",\n    \"selection\": \"#33415e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"ayu_light\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff3333\",\n    \"green\": \"#86b300\",\n    \"yellow\": \"#f29718\",\n    \"blue\": \"#41a6d9\",\n    \"magenta\": \"#f07178\",\n    \"cyan\": \"#4dbf99\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#ff6565\",\n    \"brightGreen\": \"#b8e532\",\n    \"brightYellow\": \"#ffc94a\",\n    \"brightBlue\": \"#73d8ff\",\n    \"brightMagenta\": \"#ffa3aa\",\n    \"brightCyan\": \"#7ff1cb\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#fafafa\",\n    \"foreground\": \"#5c6773\",\n    \"cursor\": \"#ff6a00\",\n    \"selection\": \"#f0eee4\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"alebcay\",\n          \"link\": \"https://github.com/alebcay\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Banana Blueberry\",\n    \"black\": \"#17141f\",\n    \"red\": \"#ff6b7f\",\n    \"green\": \"#00bd9c\",\n    \"yellow\": \"#e6c62f\",\n    \"blue\": \"#22e8df\",\n    \"magenta\": \"#dc396a\",\n    \"cyan\": \"#56b6c2\",\n    \"white\": \"#f1f1f1\",\n    \"brightBlack\": \"#495162\",\n    \"brightRed\": \"#fe9ea1\",\n    \"brightGreen\": \"#98c379\",\n    \"brightYellow\": \"#f9e46b\",\n    \"brightBlue\": \"#91fff4\",\n    \"brightMagenta\": \"#da70d6\",\n    \"brightCyan\": \"#bcf3ff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#191323\",\n    \"foreground\": \"#cccccc\",\n    \"cursor\": \"#e07d13\",\n    \"selection\": \"#220525\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ReagentX\",\n          \"link\": \"https://github.com/ReagentX\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Batman\",\n    \"black\": \"#1b1d1e\",\n    \"red\": \"#e6dc44\",\n    \"green\": \"#c8be46\",\n    \"yellow\": \"#f4fd22\",\n    \"blue\": \"#737174\",\n    \"magenta\": \"#747271\",\n    \"cyan\": \"#62605f\",\n    \"white\": \"#c6c5bf\",\n    \"brightBlack\": \"#505354\",\n    \"brightRed\": \"#fff78e\",\n    \"brightGreen\": \"#fff27d\",\n    \"brightYellow\": \"#feed6c\",\n    \"brightBlue\": \"#919495\",\n    \"brightMagenta\": \"#9a9a9d\",\n    \"brightCyan\": \"#a3a3a6\",\n    \"brightWhite\": \"#dadbd6\",\n    \"background\": \"#1b1d1e\",\n    \"foreground\": \"#6f6f6f\",\n    \"cursor\": \"#fcef0c\",\n    \"selection\": \"#4d504c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"pyrophos\",\n          \"link\": \"https://github.com/pyrophos\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Belafonte Day\",\n    \"black\": \"#20111b\",\n    \"red\": \"#be100e\",\n    \"green\": \"#858162\",\n    \"yellow\": \"#eaa549\",\n    \"blue\": \"#426a79\",\n    \"magenta\": \"#97522c\",\n    \"cyan\": \"#989a9c\",\n    \"white\": \"#968c83\",\n    \"brightBlack\": \"#5e5252\",\n    \"brightRed\": \"#be100e\",\n    \"brightGreen\": \"#858162\",\n    \"brightYellow\": \"#eaa549\",\n    \"brightBlue\": \"#426a79\",\n    \"brightMagenta\": \"#97522c\",\n    \"brightCyan\": \"#989a9c\",\n    \"brightWhite\": \"#d5ccba\",\n    \"background\": \"#d5ccba\",\n    \"foreground\": \"#45373c\",\n    \"cursor\": \"#45373c\",\n    \"selection\": \"#968c83\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"idleberg\",\n          \"link\": \"https://github.com/idleberg\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Belafonte Night\",\n    \"black\": \"#20111b\",\n    \"red\": \"#be100e\",\n    \"green\": \"#858162\",\n    \"yellow\": \"#eaa549\",\n    \"blue\": \"#426a79\",\n    \"magenta\": \"#97522c\",\n    \"cyan\": \"#989a9c\",\n    \"white\": \"#968c83\",\n    \"brightBlack\": \"#5e5252\",\n    \"brightRed\": \"#be100e\",\n    \"brightGreen\": \"#858162\",\n    \"brightYellow\": \"#eaa549\",\n    \"brightBlue\": \"#426a79\",\n    \"brightMagenta\": \"#97522c\",\n    \"brightCyan\": \"#989a9c\",\n    \"brightWhite\": \"#d5ccba\",\n    \"background\": \"#20111b\",\n    \"foreground\": \"#968c83\",\n    \"cursor\": \"#968c83\",\n    \"selection\": \"#45373c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"idleberg\",\n          \"link\": \"https://github.com/idleberg\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"BirdsOfParadise\",\n    \"black\": \"#573d26\",\n    \"red\": \"#be2d26\",\n    \"green\": \"#6ba18a\",\n    \"yellow\": \"#e99d2a\",\n    \"blue\": \"#5a86ad\",\n    \"magenta\": \"#ac80a6\",\n    \"cyan\": \"#74a6ad\",\n    \"white\": \"#e0dbb7\",\n    \"brightBlack\": \"#9b6c4a\",\n    \"brightRed\": \"#e84627\",\n    \"brightGreen\": \"#95d8ba\",\n    \"brightYellow\": \"#d0d150\",\n    \"brightBlue\": \"#b8d3ed\",\n    \"brightMagenta\": \"#d19ecb\",\n    \"brightCyan\": \"#93cfd7\",\n    \"brightWhite\": \"#fff9d5\",\n    \"background\": \"#2a1f1d\",\n    \"foreground\": \"#e0dbb7\",\n    \"cursor\": \"#573d26\",\n    \"selection\": \"#563c27\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Blazer\",\n    \"black\": \"#000000\",\n    \"red\": \"#b87a7a\",\n    \"green\": \"#7ab87a\",\n    \"yellow\": \"#b8b87a\",\n    \"blue\": \"#7a7ab8\",\n    \"magenta\": \"#b87ab8\",\n    \"cyan\": \"#7ab8b8\",\n    \"white\": \"#d9d9d9\",\n    \"brightBlack\": \"#262626\",\n    \"brightRed\": \"#dbbdbd\",\n    \"brightGreen\": \"#bddbbd\",\n    \"brightYellow\": \"#dbdbbd\",\n    \"brightBlue\": \"#bdbddb\",\n    \"brightMagenta\": \"#dbbddb\",\n    \"brightCyan\": \"#bddbdb\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0d1926\",\n    \"foreground\": \"#d9e6f2\",\n    \"cursor\": \"#d9e6f2\",\n    \"selection\": \"#c1ddff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Blue Matrix\",\n    \"black\": \"#101116\",\n    \"red\": \"#ff5680\",\n    \"green\": \"#00ff9c\",\n    \"yellow\": \"#fffc58\",\n    \"blue\": \"#00b0ff\",\n    \"magenta\": \"#d57bff\",\n    \"cyan\": \"#76c1ff\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff6e67\",\n    \"brightGreen\": \"#5ffa68\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#d682ec\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#101116\",\n    \"foreground\": \"#00a2ff\",\n    \"cursor\": \"#76ff9f\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ReagentX\",\n          \"link\": \"https://github.com/ReagentX\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"BlueBerryPie\",\n    \"black\": \"#0a4c62\",\n    \"red\": \"#99246e\",\n    \"green\": \"#5cb1b3\",\n    \"yellow\": \"#eab9a8\",\n    \"blue\": \"#90a5bd\",\n    \"magenta\": \"#9d54a7\",\n    \"cyan\": \"#7e83cc\",\n    \"white\": \"#f0e8d6\",\n    \"brightBlack\": \"#201637\",\n    \"brightRed\": \"#c87272\",\n    \"brightGreen\": \"#0a6c7e\",\n    \"brightYellow\": \"#7a3188\",\n    \"brightBlue\": \"#39173d\",\n    \"brightMagenta\": \"#bc94b7\",\n    \"brightCyan\": \"#5e6071\",\n    \"brightWhite\": \"#0a6c7e\",\n    \"background\": \"#1c0c28\",\n    \"foreground\": \"#babab9\",\n    \"cursor\": \"#fcfad6\",\n    \"selection\": \"#606060\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"murmurlilia\",\n          \"link\": \"https://www.instagram.com/the.julias\"\n        },\n        {\n          \"name\": \"fitz123\",\n          \"link\": \"https://github.com/fitz123\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"BlueDolphin\",\n    \"black\": \"#292d3e\",\n    \"red\": \"#ff8288\",\n    \"green\": \"#b4e88d\",\n    \"yellow\": \"#f4d69f\",\n    \"blue\": \"#82aaff\",\n    \"magenta\": \"#e9c1ff\",\n    \"cyan\": \"#89ebff\",\n    \"white\": \"#d0d0d0\",\n    \"brightBlack\": \"#434758\",\n    \"brightRed\": \"#ff8b92\",\n    \"brightGreen\": \"#ddffa7\",\n    \"brightYellow\": \"#ffe585\",\n    \"brightBlue\": \"#9cc4ff\",\n    \"brightMagenta\": \"#ddb0f6\",\n    \"brightCyan\": \"#a3f7ff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#006984\",\n    \"foreground\": \"#c5f2ff\",\n    \"cursor\": \"#ffcc00\",\n    \"selection\": \"#2baeca\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"BlulocoDark\",\n    \"black\": \"#41444d\",\n    \"red\": \"#fc2f52\",\n    \"green\": \"#25a45c\",\n    \"yellow\": \"#ff936a\",\n    \"blue\": \"#3476ff\",\n    \"magenta\": \"#7a82da\",\n    \"cyan\": \"#4483aa\",\n    \"white\": \"#cdd4e0\",\n    \"brightBlack\": \"#8f9aae\",\n    \"brightRed\": \"#ff6480\",\n    \"brightGreen\": \"#3fc56b\",\n    \"brightYellow\": \"#f9c859\",\n    \"brightBlue\": \"#10b1fe\",\n    \"brightMagenta\": \"#ff78f8\",\n    \"brightCyan\": \"#5fb9bc\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#282c34\",\n    \"foreground\": \"#b9c0cb\",\n    \"cursor\": \"#ffcc00\",\n    \"selection\": \"#b9c0ca\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"BlulocoLight\",\n    \"black\": \"#373a41\",\n    \"red\": \"#d52753\",\n    \"green\": \"#23974a\",\n    \"yellow\": \"#df631c\",\n    \"blue\": \"#275fe4\",\n    \"magenta\": \"#823ff1\",\n    \"cyan\": \"#27618d\",\n    \"white\": \"#babbc2\",\n    \"brightBlack\": \"#676a77\",\n    \"brightRed\": \"#ff6480\",\n    \"brightGreen\": \"#3cbc66\",\n    \"brightYellow\": \"#c5a332\",\n    \"brightBlue\": \"#0099e1\",\n    \"brightMagenta\": \"#ce33c0\",\n    \"brightCyan\": \"#6d93bb\",\n    \"brightWhite\": \"#d3d3d3\",\n    \"background\": \"#f9f9f9\",\n    \"foreground\": \"#373a41\",\n    \"cursor\": \"#f32759\",\n    \"selection\": \"#daf0ff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Borland\",\n    \"black\": \"#4f4f4f\",\n    \"red\": \"#ff6c60\",\n    \"green\": \"#a8ff60\",\n    \"yellow\": \"#ffffb6\",\n    \"blue\": \"#96cbfe\",\n    \"magenta\": \"#ff73fd\",\n    \"cyan\": \"#c6c5fe\",\n    \"white\": \"#eeeeee\",\n    \"brightBlack\": \"#7c7c7c\",\n    \"brightRed\": \"#ffb6b0\",\n    \"brightGreen\": \"#ceffac\",\n    \"brightYellow\": \"#ffffcc\",\n    \"brightBlue\": \"#b5dcff\",\n    \"brightMagenta\": \"#ff9cfe\",\n    \"brightCyan\": \"#dfdffe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0000a4\",\n    \"foreground\": \"#ffff4e\",\n    \"cursor\": \"#ffa560\",\n    \"selection\": \"#a4a4a4\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"delip\",\n          \"link\": \"https://gist.github.com/delip/9e16c606d9331d69d681\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Breeze\",\n    \"black\": \"#31363b\",\n    \"red\": \"#ed1515\",\n    \"green\": \"#11d116\",\n    \"yellow\": \"#f67400\",\n    \"blue\": \"#1d99f3\",\n    \"magenta\": \"#9b59b6\",\n    \"cyan\": \"#1abc9c\",\n    \"white\": \"#eff0f1\",\n    \"brightBlack\": \"#7f8c8d\",\n    \"brightRed\": \"#c0392b\",\n    \"brightGreen\": \"#1cdc9a\",\n    \"brightYellow\": \"#fdbc4b\",\n    \"brightBlue\": \"#3daee9\",\n    \"brightMagenta\": \"#8e44ad\",\n    \"brightCyan\": \"#16a085\",\n    \"brightWhite\": \"#fcfcfc\",\n    \"background\": \"#31363b\",\n    \"foreground\": \"#eff0f1\",\n    \"cursor\": \"#eff0f1\",\n    \"selection\": \"#eff0f1\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"KDE\",\n          \"link\": \"https://kde.org\"\n        },\n        {\n          \"name\": \"nieltg\",\n          \"link\": \"https://github.com/nieltg\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Bright Lights\",\n    \"black\": \"#191919\",\n    \"red\": \"#ff355b\",\n    \"green\": \"#b7e876\",\n    \"yellow\": \"#ffc251\",\n    \"blue\": \"#76d4ff\",\n    \"magenta\": \"#ba76e7\",\n    \"cyan\": \"#6cbfb5\",\n    \"white\": \"#c2c8d7\",\n    \"brightBlack\": \"#191919\",\n    \"brightRed\": \"#ff355b\",\n    \"brightGreen\": \"#b7e876\",\n    \"brightYellow\": \"#ffc251\",\n    \"brightBlue\": \"#76d5ff\",\n    \"brightMagenta\": \"#ba76e7\",\n    \"brightCyan\": \"#6cbfb5\",\n    \"brightWhite\": \"#c2c8d7\",\n    \"background\": \"#191919\",\n    \"foreground\": \"#b3c9d7\",\n    \"cursor\": \"#f34b00\",\n    \"selection\": \"#b3c9d7\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"tw15egan\",\n          \"link\": \"https://github.com/tw15egan\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Broadcast\",\n    \"black\": \"#000000\",\n    \"red\": \"#da4939\",\n    \"green\": \"#519f50\",\n    \"yellow\": \"#ffd24a\",\n    \"blue\": \"#6d9cbe\",\n    \"magenta\": \"#d0d0ff\",\n    \"cyan\": \"#6e9cbe\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#ff7b6b\",\n    \"brightGreen\": \"#83d182\",\n    \"brightYellow\": \"#ffff7c\",\n    \"brightBlue\": \"#9fcef0\",\n    \"brightMagenta\": \"#ffffff\",\n    \"brightCyan\": \"#a0cef0\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#2b2b2b\",\n    \"foreground\": \"#e6e1dc\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#5a647e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vinkla\",\n          \"link\": \"https://github.com/vinkla/broadcast-theme\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Brogrammer\",\n    \"black\": \"#1f1f1f\",\n    \"red\": \"#f81118\",\n    \"green\": \"#2dc55e\",\n    \"yellow\": \"#ecba0f\",\n    \"blue\": \"#2a84d2\",\n    \"magenta\": \"#4e5ab7\",\n    \"cyan\": \"#1081d6\",\n    \"white\": \"#d6dbe5\",\n    \"brightBlack\": \"#d6dbe5\",\n    \"brightRed\": \"#de352e\",\n    \"brightGreen\": \"#1dd361\",\n    \"brightYellow\": \"#f3bd09\",\n    \"brightBlue\": \"#1081d6\",\n    \"brightMagenta\": \"#5350b9\",\n    \"brightCyan\": \"#0f7ddb\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#131313\",\n    \"foreground\": \"#d6dbe5\",\n    \"cursor\": \"#b9b9b9\",\n    \"selection\": \"#1f1f1f\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"bahlo\",\n          \"link\": \"https://github.com/bahlo/iterm-colors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Bubbles\",\n    \"background\": \"#161D38\",\n    \"black\": \"#000000\",\n    \"blue\": \"#589DF6\",\n    \"brightBlack\": \"#555555\",\n    \"brightBlue\": \"#589DF6\",\n    \"brightCyan\": \"#3979BC\",\n    \"brightGreen\": \"#35BB9A\",\n    \"brightMagenta\": \"#E75699\",\n    \"brightRed\": \"#FA8C8F\",\n    \"brightWhite\": \"#FFFFFF\",\n    \"brightYellow\": \"#FFFF55\",\n    \"cursor\": \"#BBBBBB\",\n    \"cyan\": \"#1F9EE7\",\n    \"foreground\": \"#FFFFFF\",\n    \"green\": \"#21B089\",\n    \"magenta\": \"#944D95\",\n    \"red\": \"#F9555F\",\n    \"selection\": \"#B5D5FF\",\n    \"white\": \"#BBBBBB\",\n    \"yellow\": \"#FEF02A\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jos3s\",\n          \"link\": \"https://github.com/jos3s\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Builtin Dark\",\n    \"black\": \"#000000\",\n    \"red\": \"#bb0000\",\n    \"green\": \"#00bb00\",\n    \"yellow\": \"#bbbb00\",\n    \"blue\": \"#0000bb\",\n    \"magenta\": \"#bb00bb\",\n    \"cyan\": \"#00bbbb\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#bbbbbb\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Builtin Light\",\n    \"black\": \"#000000\",\n    \"red\": \"#bb0000\",\n    \"green\": \"#00bb00\",\n    \"yellow\": \"#bbbb00\",\n    \"blue\": \"#0000bb\",\n    \"magenta\": \"#bb00bb\",\n    \"cyan\": \"#00bbbb\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Builtin Pastel Dark\",\n    \"black\": \"#4f4f4f\",\n    \"red\": \"#ff6c60\",\n    \"green\": \"#a8ff60\",\n    \"yellow\": \"#ffffb6\",\n    \"blue\": \"#96cbfe\",\n    \"magenta\": \"#ff73fd\",\n    \"cyan\": \"#c6c5fe\",\n    \"white\": \"#eeeeee\",\n    \"brightBlack\": \"#7c7c7c\",\n    \"brightRed\": \"#ffb6b0\",\n    \"brightGreen\": \"#ceffac\",\n    \"brightYellow\": \"#ffffcc\",\n    \"brightBlue\": \"#b5dcff\",\n    \"brightMagenta\": \"#ff9cfe\",\n    \"brightCyan\": \"#dfdffe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#bbbbbb\",\n    \"cursor\": \"#ffa560\",\n    \"selection\": \"#363983\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Builtin Solarized Dark\",\n    \"black\": \"#073642\",\n    \"red\": \"#dc322f\",\n    \"green\": \"#859900\",\n    \"yellow\": \"#b58900\",\n    \"blue\": \"#268bd2\",\n    \"magenta\": \"#d33682\",\n    \"cyan\": \"#2aa198\",\n    \"white\": \"#eee8d5\",\n    \"brightBlack\": \"#002b36\",\n    \"brightRed\": \"#cb4b16\",\n    \"brightGreen\": \"#586e75\",\n    \"brightYellow\": \"#657b83\",\n    \"brightBlue\": \"#839496\",\n    \"brightMagenta\": \"#6c71c4\",\n    \"brightCyan\": \"#93a1a1\",\n    \"brightWhite\": \"#fdf6e3\",\n    \"background\": \"#002b36\",\n    \"foreground\": \"#839496\",\n    \"cursor\": \"#839496\",\n    \"selection\": \"#073642\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Solarized web site\",\n          \"link\": \"http://ethanschoonover.com/solarized\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Builtin Solarized Light\",\n    \"black\": \"#073642\",\n    \"red\": \"#dc322f\",\n    \"green\": \"#859900\",\n    \"yellow\": \"#b58900\",\n    \"blue\": \"#268bd2\",\n    \"magenta\": \"#d33682\",\n    \"cyan\": \"#2aa198\",\n    \"white\": \"#eee8d5\",\n    \"brightBlack\": \"#002b36\",\n    \"brightRed\": \"#cb4b16\",\n    \"brightGreen\": \"#586e75\",\n    \"brightYellow\": \"#657b83\",\n    \"brightBlue\": \"#839496\",\n    \"brightMagenta\": \"#6c71c4\",\n    \"brightCyan\": \"#93a1a1\",\n    \"brightWhite\": \"#fdf6e3\",\n    \"background\": \"#fdf6e3\",\n    \"foreground\": \"#657b83\",\n    \"cursor\": \"#657b83\",\n    \"selection\": \"#eee8d5\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"Solarized web site\",\n          \"link\": \"http://ethanschoonover.com/solarized\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Builtin Tango Dark\",\n    \"black\": \"#000000\",\n    \"red\": \"#cc0000\",\n    \"green\": \"#4e9a06\",\n    \"yellow\": \"#c4a000\",\n    \"blue\": \"#3465a4\",\n    \"magenta\": \"#75507b\",\n    \"cyan\": \"#06989a\",\n    \"white\": \"#d3d7cf\",\n    \"brightBlack\": \"#555753\",\n    \"brightRed\": \"#ef2929\",\n    \"brightGreen\": \"#8ae234\",\n    \"brightYellow\": \"#fce94f\",\n    \"brightBlue\": \"#729fcf\",\n    \"brightMagenta\": \"#ad7fa8\",\n    \"brightCyan\": \"#34e2e2\",\n    \"brightWhite\": \"#eeeeec\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Builtin Tango Light\",\n    \"black\": \"#000000\",\n    \"red\": \"#cc0000\",\n    \"green\": \"#4e9a06\",\n    \"yellow\": \"#c4a000\",\n    \"blue\": \"#3465a4\",\n    \"magenta\": \"#75507b\",\n    \"cyan\": \"#06989a\",\n    \"white\": \"#d3d7cf\",\n    \"brightBlack\": \"#555753\",\n    \"brightRed\": \"#ef2929\",\n    \"brightGreen\": \"#8ae234\",\n    \"brightYellow\": \"#fce94f\",\n    \"brightBlue\": \"#729fcf\",\n    \"brightMagenta\": \"#ad7fa8\",\n    \"brightCyan\": \"#34e2e2\",\n    \"brightWhite\": \"#eeeeec\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"C64\",\n    \"black\": \"#090300\",\n    \"red\": \"#883932\",\n    \"green\": \"#55a049\",\n    \"yellow\": \"#bfce72\",\n    \"blue\": \"#40318d\",\n    \"magenta\": \"#8b3f96\",\n    \"cyan\": \"#67b6bd\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#883932\",\n    \"brightGreen\": \"#55a049\",\n    \"brightYellow\": \"#bfce72\",\n    \"brightBlue\": \"#40318d\",\n    \"brightMagenta\": \"#8b3f96\",\n    \"brightCyan\": \"#67b6bd\",\n    \"brightWhite\": \"#f7f7f7\",\n    \"background\": \"#40318d\",\n    \"foreground\": \"#7869c4\",\n    \"cursor\": \"#7869c4\",\n    \"selection\": \"#7869c4\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"idleberg\",\n          \"link\": \"https://github.com/idleberg\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Calamity\",\n    \"black\": \"#2f2833\",\n    \"red\": \"#fc644d\",\n    \"green\": \"#a5f69c\",\n    \"yellow\": \"#e9d7a5\",\n    \"blue\": \"#3b79c7\",\n    \"magenta\": \"#f92672\",\n    \"cyan\": \"#74d3de\",\n    \"white\": \"#d5ced9\",\n    \"brightBlack\": \"#7e6c88\",\n    \"brightRed\": \"#fc644d\",\n    \"brightGreen\": \"#a5f69c\",\n    \"brightYellow\": \"#e9d7a5\",\n    \"brightBlue\": \"#3b79c7\",\n    \"brightMagenta\": \"#f92672\",\n    \"brightCyan\": \"#74d3de\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#2f2833\",\n    \"foreground\": \"#d5ced9\",\n    \"cursor\": \"#d5ced9\",\n    \"selection\": \"#7e6c88\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Pustur\",\n          \"link\": \"https://github.com/Pustur\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Catppuccin Frappe\",\n    \"black\": \"#51576d\",\n    \"red\": \"#e78284\",\n    \"green\": \"#a6d189\",\n    \"yellow\": \"#e5c890\",\n    \"blue\": \"#8caaee\",\n    \"magenta\": \"#f4b8e4\",\n    \"cyan\": \"#81c8be\",\n    \"white\": \"#b5bfe2\",\n    \"brightBlack\": \"#626880\",\n    \"brightRed\": \"#e78284\",\n    \"brightGreen\": \"#a6d189\",\n    \"brightYellow\": \"#e5c890\",\n    \"brightBlue\": \"#8caaee\",\n    \"brightMagenta\": \"#f4b8e4\",\n    \"brightCyan\": \"#81c8be\",\n    \"brightWhite\": \"#a5adce\",\n    \"background\": \"#303446\",\n    \"foreground\": \"#c6d0f5\",\n    \"selection\": \"#626880\",\n    \"cursor\": \"#f2d5cf\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Catppuccin Latte\",\n    \"black\": \"#5c5f77\",\n    \"red\": \"#d20f39\",\n    \"green\": \"#40a02b\",\n    \"yellow\": \"#df8e1d\",\n    \"blue\": \"#1e66f5\",\n    \"magenta\": \"#ea76cb\",\n    \"cyan\": \"#179299\",\n    \"white\": \"#acb0be\",\n    \"brightBlack\": \"#6c6f85\",\n    \"brightRed\": \"#d20f39\",\n    \"brightGreen\": \"#40a02b\",\n    \"brightYellow\": \"#df8e1d\",\n    \"brightBlue\": \"#1e66f5\",\n    \"brightMagenta\": \"#ea76cb\",\n    \"brightCyan\": \"#179299\",\n    \"brightWhite\": \"#bcc0cc\",\n    \"background\": \"#eff1f5\",\n    \"foreground\": \"#4c4f69\",\n    \"selection\": \"#acb0be\",\n    \"cursor\": \"#dc8a78\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Catppuccin Macchiato\",\n    \"black\": \"#494d64\",\n    \"red\": \"#ed8796\",\n    \"green\": \"#a6da95\",\n    \"yellow\": \"#eed49f\",\n    \"blue\": \"#8aadf4\",\n    \"magenta\": \"#f5bde6\",\n    \"cyan\": \"#8bd5ca\",\n    \"white\": \"#b8c0e0\",\n    \"brightBlack\": \"#5b6078\",\n    \"brightRed\": \"#ed8796\",\n    \"brightGreen\": \"#a6da95\",\n    \"brightYellow\": \"#eed49f\",\n    \"brightBlue\": \"#8aadf4\",\n    \"brightMagenta\": \"#f5bde6\",\n    \"brightCyan\": \"#8bd5ca\",\n    \"brightWhite\": \"#b8c0e0\",\n    \"background\": \"#24273a\",\n    \"foreground\": \"#cad3f5\",\n    \"selection\": \"#5b6078\",\n    \"cursor\": \"#f4dbd6\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Catppuccin Mocha\",\n    \"black\": \"#45475a\",\n    \"red\": \"#f38ba8\",\n    \"green\": \"#a6e3a1\",\n    \"yellow\": \"#f9e2af\",\n    \"blue\": \"#89b4fa\",\n    \"magenta\": \"#f5c2e7\",\n    \"cyan\": \"#94e2d5\",\n    \"white\": \"#bac2de\",\n    \"brightBlack\": \"#585b70\",\n    \"brightRed\": \"#f38ba8\",\n    \"brightGreen\": \"#a6e3a1\",\n    \"brightYellow\": \"#f9e2af\",\n    \"brightBlue\": \"#89b4fa\",\n    \"brightMagenta\": \"#f5c2e7\",\n    \"brightCyan\": \"#94e2d5\",\n    \"brightWhite\": \"#a6adc8\",\n    \"background\": \"#1e1e2e\",\n    \"foreground\": \"#cdd6f4\",\n    \"selection\": \"#585b70\",\n    \"cursor\": \"#f5e0dc\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"catppuccin-frappe\",\n    \"black\": \"#51576d\",\n    \"red\": \"#e78284\",\n    \"green\": \"#a6d189\",\n    \"yellow\": \"#e5c890\",\n    \"blue\": \"#8caaee\",\n    \"magenta\": \"#f4b8e4\",\n    \"cyan\": \"#81c8be\",\n    \"white\": \"#b5bfe2\",\n    \"brightBlack\": \"#626880\",\n    \"brightRed\": \"#e78284\",\n    \"brightGreen\": \"#a6d189\",\n    \"brightYellow\": \"#e5c890\",\n    \"brightBlue\": \"#8caaee\",\n    \"brightMagenta\": \"#f4b8e4\",\n    \"brightCyan\": \"#81c8be\",\n    \"brightWhite\": \"#a5adce\",\n    \"background\": \"#303446\",\n    \"foreground\": \"#c6d0f5\",\n    \"cursor\": \"#f2d5cf\",\n    \"selection\": \"#626880\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"catppuccin-latte\",\n    \"black\": \"#5c5f77\",\n    \"red\": \"#d20f39\",\n    \"green\": \"#40a02b\",\n    \"yellow\": \"#df8e1d\",\n    \"blue\": \"#1e66f5\",\n    \"magenta\": \"#ea76cb\",\n    \"cyan\": \"#179299\",\n    \"white\": \"#acb0be\",\n    \"brightBlack\": \"#6c6f85\",\n    \"brightRed\": \"#d20f39\",\n    \"brightGreen\": \"#40a02b\",\n    \"brightYellow\": \"#df8e1d\",\n    \"brightBlue\": \"#1e66f5\",\n    \"brightMagenta\": \"#ea76cb\",\n    \"brightCyan\": \"#179299\",\n    \"brightWhite\": \"#bcc0cc\",\n    \"background\": \"#eff1f5\",\n    \"foreground\": \"#4c4f69\",\n    \"cursor\": \"#dc8a78\",\n    \"selection\": \"#acb0be\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"catppuccin-macchiato\",\n    \"black\": \"#494d64\",\n    \"red\": \"#ed8796\",\n    \"green\": \"#a6da95\",\n    \"yellow\": \"#eed49f\",\n    \"blue\": \"#8aadf4\",\n    \"magenta\": \"#f5bde6\",\n    \"cyan\": \"#8bd5ca\",\n    \"white\": \"#b8c0e0\",\n    \"brightBlack\": \"#5b6078\",\n    \"brightRed\": \"#ed8796\",\n    \"brightGreen\": \"#a6da95\",\n    \"brightYellow\": \"#eed49f\",\n    \"brightBlue\": \"#8aadf4\",\n    \"brightMagenta\": \"#f5bde6\",\n    \"brightCyan\": \"#8bd5ca\",\n    \"brightWhite\": \"#a5adcb\",\n    \"background\": \"#24273a\",\n    \"foreground\": \"#cad3f5\",\n    \"cursor\": \"#f4dbd6\",\n    \"selection\": \"#5b6078\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"catppuccin-mocha\",\n    \"black\": \"#45475a\",\n    \"red\": \"#f38ba8\",\n    \"green\": \"#a6e3a1\",\n    \"yellow\": \"#f9e2af\",\n    \"blue\": \"#89b4fa\",\n    \"magenta\": \"#f5c2e7\",\n    \"cyan\": \"#94e2d5\",\n    \"white\": \"#bac2de\",\n    \"brightBlack\": \"#585b70\",\n    \"brightRed\": \"#f38ba8\",\n    \"brightGreen\": \"#a6e3a1\",\n    \"brightYellow\": \"#f9e2af\",\n    \"brightBlue\": \"#89b4fa\",\n    \"brightMagenta\": \"#f5c2e7\",\n    \"brightCyan\": \"#94e2d5\",\n    \"brightWhite\": \"#a6adc8\",\n    \"background\": \"#1e1e2e\",\n    \"foreground\": \"#cdd6f4\",\n    \"cursor\": \"#f5e0dc\",\n    \"selection\": \"#585b70\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"CGA\",\n    \"black\": \"#000000\",\n    \"red\": \"#aa0000\",\n    \"green\": \"#00aa00\",\n    \"yellow\": \"#aa5500\",\n    \"blue\": \"#0000aa\",\n    \"magenta\": \"#aa00aa\",\n    \"cyan\": \"#00aaaa\",\n    \"white\": \"#aaaaaa\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#aaaaaa\",\n    \"cursor\": \"#b8b8b8\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Chalk\",\n    \"black\": \"#7d8b8f\",\n    \"red\": \"#b23a52\",\n    \"green\": \"#789b6a\",\n    \"yellow\": \"#b9ac4a\",\n    \"blue\": \"#2a7fac\",\n    \"magenta\": \"#bd4f5a\",\n    \"cyan\": \"#44a799\",\n    \"white\": \"#d2d8d9\",\n    \"brightBlack\": \"#888888\",\n    \"brightRed\": \"#f24840\",\n    \"brightGreen\": \"#80c470\",\n    \"brightYellow\": \"#ffeb62\",\n    \"brightBlue\": \"#4196ff\",\n    \"brightMagenta\": \"#fc5275\",\n    \"brightCyan\": \"#53cdbd\",\n    \"brightWhite\": \"#d2d8d9\",\n    \"background\": \"#2b2d2e\",\n    \"foreground\": \"#d2d8d9\",\n    \"cursor\": \"#708284\",\n    \"selection\": \"#e4e8ed\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"achalv\",\n          \"link\": \"https://github.com/achalv/chalk\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Chalkboard\",\n    \"black\": \"#000000\",\n    \"red\": \"#c37372\",\n    \"green\": \"#72c373\",\n    \"yellow\": \"#c2c372\",\n    \"blue\": \"#7372c3\",\n    \"magenta\": \"#c372c2\",\n    \"cyan\": \"#72c2c3\",\n    \"white\": \"#d9d9d9\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#dbaaaa\",\n    \"brightGreen\": \"#aadbaa\",\n    \"brightYellow\": \"#dadbaa\",\n    \"brightBlue\": \"#aaaadb\",\n    \"brightMagenta\": \"#dbaada\",\n    \"brightCyan\": \"#aadadb\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#29262f\",\n    \"foreground\": \"#d9e6f2\",\n    \"cursor\": \"#d9e6f2\",\n    \"selection\": \"#073642\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"ChallengerDeep\",\n    \"black\": \"#141228\",\n    \"red\": \"#ff5458\",\n    \"green\": \"#62d196\",\n    \"yellow\": \"#ffb378\",\n    \"blue\": \"#65b2ff\",\n    \"magenta\": \"#906cff\",\n    \"cyan\": \"#63f2f1\",\n    \"white\": \"#a6b3cc\",\n    \"brightBlack\": \"#565575\",\n    \"brightRed\": \"#ff8080\",\n    \"brightGreen\": \"#95ffa4\",\n    \"brightYellow\": \"#ffe9aa\",\n    \"brightBlue\": \"#91ddff\",\n    \"brightMagenta\": \"#c991e1\",\n    \"brightCyan\": \"#aaffe4\",\n    \"brightWhite\": \"#cbe3e7\",\n    \"background\": \"#1e1c31\",\n    \"foreground\": \"#cbe1e7\",\n    \"cursor\": \"#fbfcfc\",\n    \"selection\": \"#cbe1e7\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"challenger-deep-theme\",\n          \"link\": \"https://github.com/challenger-deep-theme/vim\"\n        },\n        {\n          \"name\": \"eendroroy\",\n          \"link\": \"https://github.com/eendroroy\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Chester\",\n    \"black\": \"#080200\",\n    \"red\": \"#fa5e5b\",\n    \"green\": \"#16c98d\",\n    \"yellow\": \"#ffc83f\",\n    \"blue\": \"#288ad6\",\n    \"magenta\": \"#d34590\",\n    \"cyan\": \"#28ddde\",\n    \"white\": \"#e7e7e7\",\n    \"brightBlack\": \"#6f6b68\",\n    \"brightRed\": \"#fa5e5b\",\n    \"brightGreen\": \"#16c98d\",\n    \"brightYellow\": \"#feef6d\",\n    \"brightBlue\": \"#278ad6\",\n    \"brightMagenta\": \"#d34590\",\n    \"brightCyan\": \"#27dede\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#2c3643\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#b4b1b1\",\n    \"selection\": \"#67747c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"KH\",\n          \"link\": \"https://github.com/spectralkh\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Ciapre\",\n    \"black\": \"#181818\",\n    \"red\": \"#810009\",\n    \"green\": \"#48513b\",\n    \"yellow\": \"#cc8b3f\",\n    \"blue\": \"#576d8c\",\n    \"magenta\": \"#724d7c\",\n    \"cyan\": \"#5c4f4b\",\n    \"white\": \"#aea47f\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ac3835\",\n    \"brightGreen\": \"#a6a75d\",\n    \"brightYellow\": \"#dcdf7c\",\n    \"brightBlue\": \"#3097c6\",\n    \"brightMagenta\": \"#d33061\",\n    \"brightCyan\": \"#f3dbb2\",\n    \"brightWhite\": \"#f4f4f4\",\n    \"background\": \"#191c27\",\n    \"foreground\": \"#aea47a\",\n    \"cursor\": \"#92805b\",\n    \"selection\": \"#172539\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"CLRS\",\n    \"black\": \"#000000\",\n    \"red\": \"#f8282a\",\n    \"green\": \"#328a5d\",\n    \"yellow\": \"#fa701d\",\n    \"blue\": \"#135cd0\",\n    \"magenta\": \"#9f00bd\",\n    \"cyan\": \"#33c3c1\",\n    \"white\": \"#b3b3b3\",\n    \"brightBlack\": \"#555753\",\n    \"brightRed\": \"#fb0416\",\n    \"brightGreen\": \"#2cc631\",\n    \"brightYellow\": \"#fdd727\",\n    \"brightBlue\": \"#1670ff\",\n    \"brightMagenta\": \"#e900b0\",\n    \"brightCyan\": \"#3ad5ce\",\n    \"brightWhite\": \"#eeeeec\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#262626\",\n    \"cursor\": \"#6fd3fc\",\n    \"selection\": \"#6fd3fc\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"jasonlong\",\n          \"link\": \"https://github.com/jasonlong/iterm-clrs\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Cobalt Neon\",\n    \"black\": \"#142631\",\n    \"red\": \"#ff2320\",\n    \"green\": \"#3ba5ff\",\n    \"yellow\": \"#e9e75c\",\n    \"blue\": \"#8ff586\",\n    \"magenta\": \"#781aa0\",\n    \"cyan\": \"#8ff586\",\n    \"white\": \"#ba46b2\",\n    \"brightBlack\": \"#fff688\",\n    \"brightRed\": \"#d4312e\",\n    \"brightGreen\": \"#8ff586\",\n    \"brightYellow\": \"#e9f06d\",\n    \"brightBlue\": \"#3c7dd2\",\n    \"brightMagenta\": \"#8230a7\",\n    \"brightCyan\": \"#6cbc67\",\n    \"brightWhite\": \"#8ff586\",\n    \"background\": \"#142838\",\n    \"foreground\": \"#8ff586\",\n    \"cursor\": \"#c4206f\",\n    \"selection\": \"#094fb1\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vazquez\",\n          \"link\": \"https://github.com/vazquez/cobalt-neon-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Cobalt2\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff0000\",\n    \"green\": \"#38de21\",\n    \"yellow\": \"#ffe50a\",\n    \"blue\": \"#1460d2\",\n    \"magenta\": \"#ff005d\",\n    \"cyan\": \"#00bbbb\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#f40e17\",\n    \"brightGreen\": \"#3bd01d\",\n    \"brightYellow\": \"#edc809\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#6ae3fa\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#132738\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#f0cc09\",\n    \"selection\": \"#18354f\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"wesbos\",\n          \"link\": \"https://github.com/wesbos/Cobalt2-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"coffee_theme\",\n    \"black\": \"#000000\",\n    \"red\": \"#c91b00\",\n    \"green\": \"#00c200\",\n    \"yellow\": \"#c7c400\",\n    \"blue\": \"#0225c7\",\n    \"magenta\": \"#ca30c7\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff6e67\",\n    \"brightGreen\": \"#5ffa68\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#ff77ff\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#f5deb3\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"cbitterfield\",\n          \"link\": \"https://github.com/cbitterfield\"\n        }\n      ]\n    }\n  },\n  {\n    \"background\": \"#FFFFFF\",\n    \"black\": \"#2E1742\",\n    \"blue\": \"#0D6BAD\",\n    \"brightBlack\": \"#462366\",\n    \"brightBlue\": \"#008CCC\",\n    \"brightCyan\": \"#46D1E0\",\n    \"brightGreen\": \"#99C252\",\n    \"brightMagenta\": \"#AF87FF\",\n    \"brightRed\": \"#FF0000\",\n    \"brightWhite\": \"#FFFFFF\",\n    \"brightYellow\": \"#A39B46\",\n    \"cursor\": \"#000000\",\n    \"cyan\": \"#41C2D0\",\n    \"foreground\": \"#051840\",\n    \"green\": \"#77B01B\",\n    \"name\": \"Contrast Light\",\n    \"magenta\": \"#8700FF\",\n    \"red\": \"#BF0000\",\n    \"selection\": \"#B5D5FF\",\n    \"white\": \"#E6E6E6\",\n    \"yellow\": \"#857E39\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"background\": \"#010C18\",\n    \"black\": \"#0B3B61\",\n    \"blue\": \"#1376F9\",\n    \"brightBlack\": \"#63686D\",\n    \"brightBlue\": \"#388EFF\",\n    \"brightCyan\": \"#FF6AD7\",\n    \"brightGreen\": \"#74FFD8\",\n    \"brightMagenta\": \"#AE81FF\",\n    \"brightRed\": \"#FF54B0\",\n    \"brightWhite\": \"#60FBBF\",\n    \"brightYellow\": \"#FCF5AE\",\n    \"cursor\": \"#38FF9D\",\n    \"cyan\": \"#FF5ED4\",\n    \"foreground\": \"#ECDEF4\",\n    \"green\": \"#52FFD0\",\n    \"name\": \"coolnight\",\n    \"magenta\": \"#C792EA\",\n    \"red\": \"#FF3A3A\",\n    \"selection\": \"#38FF9C\",\n    \"white\": \"#16FDA2\",\n    \"yellow\": \"#FFF383\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"CrayonPonyFish\",\n    \"black\": \"#2b1b1d\",\n    \"red\": \"#91002b\",\n    \"green\": \"#579524\",\n    \"yellow\": \"#ab311b\",\n    \"blue\": \"#8c87b0\",\n    \"magenta\": \"#692f50\",\n    \"cyan\": \"#e8a866\",\n    \"white\": \"#68525a\",\n    \"brightBlack\": \"#3d2b2e\",\n    \"brightRed\": \"#c5255d\",\n    \"brightGreen\": \"#8dff57\",\n    \"brightYellow\": \"#c8381d\",\n    \"brightBlue\": \"#cfc9ff\",\n    \"brightMagenta\": \"#fc6cba\",\n    \"brightCyan\": \"#ffceaf\",\n    \"brightWhite\": \"#b0949d\",\n    \"background\": \"#150707\",\n    \"foreground\": \"#68525a\",\n    \"cursor\": \"#68525a\",\n    \"selection\": \"#2b1b1d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"background\": \"#1E1423\",\n    \"black\": \"#0A0A14\",\n    \"blue\": \"#5050E6\",\n    \"brightBlack\": \"#363B54\",\n    \"brightBlue\": \"#7AA2F7\",\n    \"brightCyan\": \"#7DCFFF\",\n    \"brightGreen\": \"#41A6B5\",\n    \"brightMagenta\": \"#BB9AF7\",\n    \"brightRed\": \"#F7768E\",\n    \"brightWhite\": \"#ACB0D0\",\n    \"brightYellow\": \"#E0AF68\",\n    \"cursor\": \"#2DB9E6\",\n    \"cyan\": \"#2DB9E6\",\n    \"foreground\": \"#737DA0\",\n    \"green\": \"#32CD87\",\n    \"name\": \"Crystal Violet\",\n    \"magenta\": \"#6E14EB\",\n    \"red\": \"#E63232\",\n    \"selection\": \"#5050E6\",\n    \"white\": \"#D2D2D2\",\n    \"yellow\": \"#EBA041\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"background\": \"#161C2B\",\n    \"black\": \"#141D2B\",\n    \"blue\": \"#2E6CFF\",\n    \"brightBlack\": \"#767676\",\n    \"brightBlue\": \"#5CB2FF\",\n    \"brightCyan\": \"#5CECC6\",\n    \"brightGreen\": \"#C5F467\",\n    \"brightMagenta\": \"#CF8DFB\",\n    \"brightRed\": \"#FF8484\",\n    \"brightWhite\": \"#D5DAFF\",\n    \"brightYellow\": \"#FFCC5C\",\n    \"cursor\": \"#C5D1EB\",\n    \"cyan\": \"#2DE2B2\",\n    \"foreground\": \"#A4B1CD\",\n    \"green\": \"#9FEF00\",\n    \"name\": \"Cyber Cube\",\n    \"magenta\": \"#9F00FF\",\n    \"red\": \"#FF3E3E\",\n    \"selection\": \"#C5D1EB\",\n    \"white\": \"#D5E0FF\",\n    \"yellow\": \"#FFAF00\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Cyberdyne\",\n    \"black\": \"#080808\",\n    \"red\": \"#ff8373\",\n    \"green\": \"#00c172\",\n    \"yellow\": \"#d2a700\",\n    \"blue\": \"#0071cf\",\n    \"magenta\": \"#ff90fe\",\n    \"cyan\": \"#6bffdd\",\n    \"white\": \"#f1f1f1\",\n    \"brightBlack\": \"#2e2e2e\",\n    \"brightRed\": \"#ffc4be\",\n    \"brightGreen\": \"#d6fcba\",\n    \"brightYellow\": \"#fffed5\",\n    \"brightBlue\": \"#c2e3ff\",\n    \"brightMagenta\": \"#ffb2fe\",\n    \"brightCyan\": \"#e6e7fe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#151144\",\n    \"foreground\": \"#00ff92\",\n    \"cursor\": \"#00ff9c\",\n    \"selection\": \"#454d96\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ReagentX\",\n          \"link\": \"https://github.com/ReagentX\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"cyberpunk\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff7092\",\n    \"green\": \"#00fbac\",\n    \"yellow\": \"#fffa6a\",\n    \"blue\": \"#00bfff\",\n    \"magenta\": \"#df95ff\",\n    \"cyan\": \"#86cbfe\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#ff8aa4\",\n    \"brightGreen\": \"#21f6bc\",\n    \"brightYellow\": \"#fff787\",\n    \"brightBlue\": \"#1bccfd\",\n    \"brightMagenta\": \"#e6aefe\",\n    \"brightCyan\": \"#99d6fc\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#332a57\",\n    \"foreground\": \"#e5e5e5\",\n    \"cursor\": \"#21f6bc\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Murderlon\",\n          \"link\": \"https://github.com/Murderlon/cyberpunk-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"CyberPunk2077\",\n    \"background\": \"#272932\",\n    \"black\": \"#272932\",\n    \"blue\": \"#9381FF\",\n    \"brightBlack\": \"#7b8097\",\n    \"brightBlue\": \"#37EBF3\",\n    \"brightCyan\": \"#37EBF3\",\n    \"brightGreen\": \"#40FFE9\",\n    \"brightMagenta\": \"#CB1DCD\",\n    \"brightRed\": \"#C71515\",\n    \"brightWhite\": \"#C1DEFF\",\n    \"brightYellow\": \"#fff955\",\n    \"cursor\": \"#FDF500\",\n    \"cyan\": \"#00D0DB\",\n    \"foreground\": \"#E455AE\",\n    \"green\": \"#1AC5B0\",\n    \"magenta\": \"#742D8B\",\n    \"red\": \"#710000\",\n    \"selection\": \"#742D8B\",\n    \"white\": \"#D1C5C0\",\n    \"yellow\": \"#FDF500\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Dark Pastel\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff5555\",\n    \"green\": \"#55ff55\",\n    \"yellow\": \"#ffff55\",\n    \"blue\": \"#5555ff\",\n    \"magenta\": \"#ff55ff\",\n    \"cyan\": \"#55ffff\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Dark+\",\n    \"black\": \"#000000\",\n    \"red\": \"#cd3131\",\n    \"green\": \"#0dbc79\",\n    \"yellow\": \"#e5e510\",\n    \"blue\": \"#2472c8\",\n    \"magenta\": \"#bc3fbc\",\n    \"cyan\": \"#11a8cd\",\n    \"white\": \"#e5e5e5\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#f14c4c\",\n    \"brightGreen\": \"#23d18b\",\n    \"brightYellow\": \"#f5f543\",\n    \"brightBlue\": \"#3b8eea\",\n    \"brightMagenta\": \"#d670d6\",\n    \"brightCyan\": \"#29b8db\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#1e1e1e\",\n    \"foreground\": \"#cccccc\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#3a3d41\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"darkermatrix\",\n    \"black\": \"#091013\",\n    \"red\": \"#002e18\",\n    \"green\": \"#6fa64c\",\n    \"yellow\": \"#595900\",\n    \"blue\": \"#00cb6b\",\n    \"magenta\": \"#412a4d\",\n    \"cyan\": \"#125459\",\n    \"white\": \"#002e19\",\n    \"brightBlack\": \"#333333\",\n    \"brightRed\": \"#00381d\",\n    \"brightGreen\": \"#90d762\",\n    \"brightYellow\": \"#e2e500\",\n    \"brightBlue\": \"#00ff87\",\n    \"brightMagenta\": \"#412a4d\",\n    \"brightCyan\": \"#176c73\",\n    \"brightWhite\": \"#00381e\",\n    \"background\": \"#070c0e\",\n    \"foreground\": \"#28380d\",\n    \"cursor\": \"#373a26\",\n    \"selection\": \"#0f191c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"darkmatrix\",\n    \"black\": \"#091013\",\n    \"red\": \"#006536\",\n    \"green\": \"#6fa64c\",\n    \"yellow\": \"#7e8000\",\n    \"blue\": \"#2c9a84\",\n    \"magenta\": \"#452d53\",\n    \"cyan\": \"#114d53\",\n    \"white\": \"#006536\",\n    \"brightBlack\": \"#333333\",\n    \"brightRed\": \"#00733d\",\n    \"brightGreen\": \"#90d762\",\n    \"brightYellow\": \"#e2e500\",\n    \"brightBlue\": \"#46d8b8\",\n    \"brightMagenta\": \"#4a3059\",\n    \"brightCyan\": \"#12545a\",\n    \"brightWhite\": \"#006536\",\n    \"background\": \"#070c0e\",\n    \"foreground\": \"#3e5715\",\n    \"cursor\": \"#9fa86e\",\n    \"selection\": \"#0f191c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Darkside\",\n    \"black\": \"#000000\",\n    \"red\": \"#e8341c\",\n    \"green\": \"#68c256\",\n    \"yellow\": \"#f2d42c\",\n    \"blue\": \"#1c98e8\",\n    \"magenta\": \"#8e69c9\",\n    \"cyan\": \"#1c98e8\",\n    \"white\": \"#bababa\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#e05a4f\",\n    \"brightGreen\": \"#77b869\",\n    \"brightYellow\": \"#efd64b\",\n    \"brightBlue\": \"#387cd3\",\n    \"brightMagenta\": \"#957bbe\",\n    \"brightCyan\": \"#3d97e2\",\n    \"brightWhite\": \"#bababa\",\n    \"background\": \"#222324\",\n    \"foreground\": \"#bababa\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#303333\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"bahlo\",\n          \"link\": \"https://github.com/bahlo/iterm-colors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"deep\",\n    \"black\": \"#000000\",\n    \"red\": \"#d70005\",\n    \"green\": \"#1cd915\",\n    \"yellow\": \"#d9bd26\",\n    \"blue\": \"#5665ff\",\n    \"magenta\": \"#b052da\",\n    \"cyan\": \"#50d2da\",\n    \"white\": \"#e0e0e0\",\n    \"brightBlack\": \"#535353\",\n    \"brightRed\": \"#fb0007\",\n    \"brightGreen\": \"#22ff18\",\n    \"brightYellow\": \"#fedc2b\",\n    \"brightBlue\": \"#9fa9ff\",\n    \"brightMagenta\": \"#e09aff\",\n    \"brightCyan\": \"#8df9ff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#090909\",\n    \"foreground\": \"#cdcdcd\",\n    \"cursor\": \"#d0d0d0\",\n    \"selection\": \"#780002\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ADoyle\",\n          \"link\": \"https://github.com/adoyle-h\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Desert\",\n    \"black\": \"#4d4d4d\",\n    \"red\": \"#ff2b2b\",\n    \"green\": \"#98fb98\",\n    \"yellow\": \"#f0e68c\",\n    \"blue\": \"#cd853f\",\n    \"magenta\": \"#ffdead\",\n    \"cyan\": \"#ffa0a0\",\n    \"white\": \"#f5deb3\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#87ceff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#ffd700\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#333333\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#00ff00\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"DimmedMonokai\",\n    \"black\": \"#3a3d43\",\n    \"red\": \"#be3f48\",\n    \"green\": \"#879a3b\",\n    \"yellow\": \"#c5a635\",\n    \"blue\": \"#4f76a1\",\n    \"magenta\": \"#855c8d\",\n    \"cyan\": \"#578fa4\",\n    \"white\": \"#b9bcba\",\n    \"brightBlack\": \"#888987\",\n    \"brightRed\": \"#fb001f\",\n    \"brightGreen\": \"#0f722f\",\n    \"brightYellow\": \"#c47033\",\n    \"brightBlue\": \"#186de3\",\n    \"brightMagenta\": \"#fb0067\",\n    \"brightCyan\": \"#2e706d\",\n    \"brightWhite\": \"#fdffb9\",\n    \"background\": \"#1f1f1f\",\n    \"foreground\": \"#b9bcba\",\n    \"cursor\": \"#f83e19\",\n    \"selection\": \"#2a2d32\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Django\",\n    \"black\": \"#000000\",\n    \"red\": \"#fd6209\",\n    \"green\": \"#41a83e\",\n    \"yellow\": \"#ffe862\",\n    \"blue\": \"#245032\",\n    \"magenta\": \"#f8f8f8\",\n    \"cyan\": \"#9df39f\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#ff943b\",\n    \"brightGreen\": \"#73da70\",\n    \"brightYellow\": \"#ffff94\",\n    \"brightBlue\": \"#568264\",\n    \"brightMagenta\": \"#ffffff\",\n    \"brightCyan\": \"#cfffd1\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0b2f20\",\n    \"foreground\": \"#f8f8f8\",\n    \"cursor\": \"#336442\",\n    \"selection\": \"#245032\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Jannis Leidel\",\n          \"link\": \"https://code.djangoproject.com/wiki/TextMate\"\n        },\n        {\n          \"name\": \"threespot.com\",\n          \"link\": \"https://threespot.com\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"DjangoRebornAgain\",\n    \"black\": \"#000000\",\n    \"red\": \"#fd6209\",\n    \"green\": \"#41a83e\",\n    \"yellow\": \"#ffe862\",\n    \"blue\": \"#245032\",\n    \"magenta\": \"#f8f8f8\",\n    \"cyan\": \"#9df39f\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#ff943b\",\n    \"brightGreen\": \"#73da70\",\n    \"brightYellow\": \"#ffff94\",\n    \"brightBlue\": \"#568264\",\n    \"brightMagenta\": \"#ffffff\",\n    \"brightCyan\": \"#cfffd1\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#051f14\",\n    \"foreground\": \"#dadedc\",\n    \"cursor\": \"#ffcc00\",\n    \"selection\": \"#203727\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"christopherscott\",\n          \"link\": \"https://github.com/christopherscott/django-reborn\"\n        },\n        {\n          \"name\": \"Jannis Leidel\",\n          \"link\": \"https://code.djangoproject.com/wiki/TextMate\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"DjangoSmooth\",\n    \"black\": \"#000000\",\n    \"red\": \"#fd6209\",\n    \"green\": \"#41a83e\",\n    \"yellow\": \"#ffe862\",\n    \"blue\": \"#989898\",\n    \"magenta\": \"#f8f8f8\",\n    \"cyan\": \"#9df39f\",\n    \"white\": \"#e8e8e7\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#ff943b\",\n    \"brightGreen\": \"#73da70\",\n    \"brightYellow\": \"#ffff94\",\n    \"brightBlue\": \"#cacaca\",\n    \"brightMagenta\": \"#ffffff\",\n    \"brightCyan\": \"#cfffd1\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#245032\",\n    \"foreground\": \"#f8f8f8\",\n    \"cursor\": \"#336442\",\n    \"selection\": \"#336442\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Jannis Leidel\",\n          \"link\": \"https://code.djangoproject.com/wiki/TextMate\"\n        },\n        {\n          \"name\": \"threespot.com\",\n          \"link\": \"https://threespot.com\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Doom Peacock\",\n    \"black\": \"#1c1f24\",\n    \"red\": \"#cb4b16\",\n    \"green\": \"#26a6a6\",\n    \"yellow\": \"#bcd42a\",\n    \"blue\": \"#2a6cc6\",\n    \"magenta\": \"#a9a1e1\",\n    \"cyan\": \"#5699af\",\n    \"white\": \"#ede0ce\",\n    \"brightBlack\": \"#2b2a27\",\n    \"brightRed\": \"#ff5d38\",\n    \"brightGreen\": \"#98be65\",\n    \"brightYellow\": \"#e6f972\",\n    \"brightBlue\": \"#51afef\",\n    \"brightMagenta\": \"#c678dd\",\n    \"brightCyan\": \"#46d9ff\",\n    \"brightWhite\": \"#dfdfdf\",\n    \"background\": \"#2b2a27\",\n    \"foreground\": \"#ede0ce\",\n    \"cursor\": \"#9c9c9d\",\n    \"selection\": \"#a60033\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Emacs Doom Peacock theme\",\n          \"link\": \"https://github.com/hlissner/emacs-doom-themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"DoomOne\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff6c6b\",\n    \"green\": \"#98be65\",\n    \"yellow\": \"#ecbe7b\",\n    \"blue\": \"#a9a1e1\",\n    \"magenta\": \"#c678dd\",\n    \"cyan\": \"#51afef\",\n    \"white\": \"#bbc2cf\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#ff6655\",\n    \"brightGreen\": \"#99bb66\",\n    \"brightYellow\": \"#ecbe7b\",\n    \"brightBlue\": \"#a9a1e1\",\n    \"brightMagenta\": \"#c678dd\",\n    \"brightCyan\": \"#51afef\",\n    \"brightWhite\": \"#bfbfbf\",\n    \"background\": \"#282c34\",\n    \"foreground\": \"#bbc2cf\",\n    \"cursor\": \"#51afef\",\n    \"selection\": \"#42444b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Emacs Doom default theme\",\n          \"link\": \"https://github.com/hlissner/emacs-doom-themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"DotGov\",\n    \"black\": \"#191919\",\n    \"red\": \"#bf091d\",\n    \"green\": \"#3d9751\",\n    \"yellow\": \"#f6bb34\",\n    \"blue\": \"#17b2e0\",\n    \"magenta\": \"#7830b0\",\n    \"cyan\": \"#8bd2ed\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#191919\",\n    \"brightRed\": \"#bf091d\",\n    \"brightGreen\": \"#3d9751\",\n    \"brightYellow\": \"#f6bb34\",\n    \"brightBlue\": \"#17b2e0\",\n    \"brightMagenta\": \"#7830b0\",\n    \"brightCyan\": \"#8bd2ed\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#262c35\",\n    \"foreground\": \"#ebebeb\",\n    \"cursor\": \"#d9002f\",\n    \"selection\": \"#1a4080\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"U.S. Web Design Standards\",\n          \"link\": \"https://standards.usa.gov/visual-style/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Dracula\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff5555\",\n    \"green\": \"#50fa7b\",\n    \"yellow\": \"#f1fa8c\",\n    \"blue\": \"#bd93f9\",\n    \"magenta\": \"#ff79c6\",\n    \"cyan\": \"#8be9fd\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#50fa7b\",\n    \"brightYellow\": \"#f1fa8c\",\n    \"brightBlue\": \"#bd93f9\",\n    \"brightMagenta\": \"#ff79c6\",\n    \"brightCyan\": \"#8be9fd\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1e1f29\",\n    \"foreground\": \"#f8f8f2\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#44475a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zenorocha\",\n          \"link\": \"https://github.com/zenorocha/dracula-theme\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Dracula+\",\n    \"black\": \"#21222c\",\n    \"red\": \"#ff5555\",\n    \"green\": \"#50fa7b\",\n    \"yellow\": \"#ffcb6b\",\n    \"blue\": \"#82aaff\",\n    \"magenta\": \"#c792ea\",\n    \"cyan\": \"#8be9fd\",\n    \"white\": \"#f8f8f2\",\n    \"brightBlack\": \"#545454\",\n    \"brightRed\": \"#ff6e6e\",\n    \"brightGreen\": \"#69ff94\",\n    \"brightYellow\": \"#ffcb6b\",\n    \"brightBlue\": \"#d6acff\",\n    \"brightMagenta\": \"#ff92df\",\n    \"brightCyan\": \"#a4ffff\",\n    \"brightWhite\": \"#f8f8f2\",\n    \"background\": \"#212121\",\n    \"foreground\": \"#f8f8f2\",\n    \"cursor\": \"#eceff4\",\n    \"selection\": \"#f8f8f2\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zenorocha\",\n          \"link\": \"https://github.com/zenorocha/dracula-theme\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"DraculaPlus\",\n    \"background\": \"#212121\",\n    \"black\": \"#21222C\",\n    \"blue\": \"#82aaff\",\n    \"cyan\": \"#8BE9FD\",\n    \"foreground\": \"#F8F8F2\",\n    \"green\": \"#50FA7B\",\n    \"magenta\": \"#c792ea\",\n    \"red\": \"#FF5555\",\n    \"white\": \"#F8F8F2\",\n    \"yellow\": \"#ffcb6b\",\n    \"brightBlack\": \"#545454\",\n    \"brightBlue\": \"#D6ACFF\",\n    \"brightCyan\": \"#A4FFFF\",\n    \"brightGreen\": \"#69FF94\",\n    \"brightMagenta\": \"#FF92DF\",\n    \"brightRed\": \"#FF6E6E\",\n    \"brightWhite\": \"#F8F8F2\",\n    \"brightYellow\": \"#ffcb6b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jos3s\",\n          \"link\": \"https://github.com/jos3s\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"duckbones\",\n    \"black\": \"#0e101a\",\n    \"red\": \"#e03600\",\n    \"green\": \"#5dcd97\",\n    \"yellow\": \"#e39500\",\n    \"blue\": \"#00a3cb\",\n    \"magenta\": \"#795ccc\",\n    \"cyan\": \"#00a3cb\",\n    \"white\": \"#ebefc0\",\n    \"brightBlack\": \"#2b2f46\",\n    \"brightRed\": \"#ff4821\",\n    \"brightGreen\": \"#58db9e\",\n    \"brightYellow\": \"#f6a100\",\n    \"brightBlue\": \"#00b4e0\",\n    \"brightMagenta\": \"#b3a1e6\",\n    \"brightCyan\": \"#00b4e0\",\n    \"brightWhite\": \"#b3b692\",\n    \"background\": \"#0e101a\",\n    \"foreground\": \"#ebefc0\",\n    \"cursor\": \"#edf2c2\",\n    \"selection\": \"#37382d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Duotone Dark\",\n    \"black\": \"#1f1d27\",\n    \"red\": \"#d9393e\",\n    \"green\": \"#2dcd73\",\n    \"yellow\": \"#d9b76e\",\n    \"blue\": \"#ffc284\",\n    \"magenta\": \"#de8d40\",\n    \"cyan\": \"#2488ff\",\n    \"white\": \"#b7a1ff\",\n    \"brightBlack\": \"#353147\",\n    \"brightRed\": \"#d9393e\",\n    \"brightGreen\": \"#2dcd73\",\n    \"brightYellow\": \"#d9b76e\",\n    \"brightBlue\": \"#ffc284\",\n    \"brightMagenta\": \"#de8d40\",\n    \"brightCyan\": \"#2488ff\",\n    \"brightWhite\": \"#eae5ff\",\n    \"background\": \"#1f1d27\",\n    \"foreground\": \"#b7a1ff\",\n    \"cursor\": \"#ff9839\",\n    \"selection\": \"#353147\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"chibicode\",\n          \"link\": \"http://chibicode.com\"\n        },\n        {\n          \"name\": \"simurai\",\n          \"link\": \"https://github.com/simurai\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Earthsong\",\n    \"black\": \"#121418\",\n    \"red\": \"#c94234\",\n    \"green\": \"#85c54c\",\n    \"yellow\": \"#f5ae2e\",\n    \"blue\": \"#1398b9\",\n    \"magenta\": \"#d0633d\",\n    \"cyan\": \"#509552\",\n    \"white\": \"#e5c6aa\",\n    \"brightBlack\": \"#675f54\",\n    \"brightRed\": \"#ff645a\",\n    \"brightGreen\": \"#98e036\",\n    \"brightYellow\": \"#e0d561\",\n    \"brightBlue\": \"#5fdaff\",\n    \"brightMagenta\": \"#ff9269\",\n    \"brightCyan\": \"#84f088\",\n    \"brightWhite\": \"#f6f7ec\",\n    \"background\": \"#292520\",\n    \"foreground\": \"#e5c7a9\",\n    \"cursor\": \"#f6f7ec\",\n    \"selection\": \"#121418\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Elemental\",\n    \"black\": \"#3c3c30\",\n    \"red\": \"#98290f\",\n    \"green\": \"#479a43\",\n    \"yellow\": \"#7f7111\",\n    \"blue\": \"#497f7d\",\n    \"magenta\": \"#7f4e2f\",\n    \"cyan\": \"#387f58\",\n    \"white\": \"#807974\",\n    \"brightBlack\": \"#555445\",\n    \"brightRed\": \"#e0502a\",\n    \"brightGreen\": \"#61e070\",\n    \"brightYellow\": \"#d69927\",\n    \"brightBlue\": \"#79d9d9\",\n    \"brightMagenta\": \"#cd7c54\",\n    \"brightCyan\": \"#59d599\",\n    \"brightWhite\": \"#fff1e9\",\n    \"background\": \"#22211d\",\n    \"foreground\": \"#807a74\",\n    \"cursor\": \"#facb80\",\n    \"selection\": \"#413829\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Elementary\",\n    \"black\": \"#242424\",\n    \"red\": \"#d71c15\",\n    \"green\": \"#5aa513\",\n    \"yellow\": \"#fdb40c\",\n    \"blue\": \"#063b8c\",\n    \"magenta\": \"#e40038\",\n    \"cyan\": \"#2595e1\",\n    \"white\": \"#efefef\",\n    \"brightBlack\": \"#4b4b4b\",\n    \"brightRed\": \"#fc1c18\",\n    \"brightGreen\": \"#6bc219\",\n    \"brightYellow\": \"#fec80e\",\n    \"brightBlue\": \"#0955ff\",\n    \"brightMagenta\": \"#fb0050\",\n    \"brightCyan\": \"#3ea8fc\",\n    \"brightWhite\": \"#8c00ec\",\n    \"background\": \"#181818\",\n    \"foreground\": \"#efefef\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"elementary.io\",\n          \"link\": \"https://elementary.io/\"\n        },\n        {\n          \"name\": \"987poiuytrewq\",\n          \"link\": \"https://github.com/987poiuytrewq\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"ENCOM\",\n    \"black\": \"#000000\",\n    \"red\": \"#9f0000\",\n    \"green\": \"#008b00\",\n    \"yellow\": \"#ffd000\",\n    \"blue\": \"#0081ff\",\n    \"magenta\": \"#bc00ca\",\n    \"cyan\": \"#008b8b\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff0000\",\n    \"brightGreen\": \"#00ee00\",\n    \"brightYellow\": \"#ffff00\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#ff00ff\",\n    \"brightCyan\": \"#00cdcd\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#00a595\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#00a48c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Josh Braun\",\n          \"link\": \"http://wideaperture.net\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Espresso\",\n    \"black\": \"#353535\",\n    \"red\": \"#d25252\",\n    \"green\": \"#a5c261\",\n    \"yellow\": \"#ffc66d\",\n    \"blue\": \"#6c99bb\",\n    \"magenta\": \"#d197d9\",\n    \"cyan\": \"#bed6ff\",\n    \"white\": \"#eeeeec\",\n    \"brightBlack\": \"#535353\",\n    \"brightRed\": \"#f00c0c\",\n    \"brightGreen\": \"#c2e075\",\n    \"brightYellow\": \"#e1e48b\",\n    \"brightBlue\": \"#8ab7d9\",\n    \"brightMagenta\": \"#efb5f7\",\n    \"brightCyan\": \"#dcf4ff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#323232\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#d6d6d6\",\n    \"selection\": \"#5b5b5b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Espresso Libre\",\n    \"black\": \"#000000\",\n    \"red\": \"#cc0000\",\n    \"green\": \"#1a921c\",\n    \"yellow\": \"#f0e53a\",\n    \"blue\": \"#0066ff\",\n    \"magenta\": \"#c5656b\",\n    \"cyan\": \"#06989a\",\n    \"white\": \"#d3d7cf\",\n    \"brightBlack\": \"#555753\",\n    \"brightRed\": \"#ef2929\",\n    \"brightGreen\": \"#9aff87\",\n    \"brightYellow\": \"#fffb5c\",\n    \"brightBlue\": \"#43a8ed\",\n    \"brightMagenta\": \"#ff818a\",\n    \"brightCyan\": \"#34e2e2\",\n    \"brightWhite\": \"#eeeeec\",\n    \"background\": \"#2a211c\",\n    \"foreground\": \"#b8a898\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#c3dcff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jurgemaister\",\n          \"link\": \"https://github.com/jurgemaister/Espresso-Libre\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Everblush\",\n    \"black\": \"#232a2d\",\n    \"red\": \"#e57474\",\n    \"green\": \"#8ccf7e\",\n    \"yellow\": \"#e5c76b\",\n    \"blue\": \"#67b0e8\",\n    \"magenta\": \"#c47fd5\",\n    \"cyan\": \"#6cbfbf\",\n    \"white\": \"#b3b9b8\",\n    \"brightBlack\": \"#2d3437\",\n    \"brightRed\": \"#ef7e7e\",\n    \"brightGreen\": \"#96d988\",\n    \"brightYellow\": \"#f4d67a\",\n    \"brightBlue\": \"#71baf2\",\n    \"brightMagenta\": \"#ce89df\",\n    \"brightCyan\": \"#67cbe7\",\n    \"brightWhite\": \"#bdc3c2\",\n    \"background\": \"#141b1e\",\n    \"foreground\": \"#dadada\",\n    \"cursor\": \"#dadada\",\n    \"selection\": \"#141b1e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Fahrenheit\",\n    \"black\": \"#1d1d1d\",\n    \"red\": \"#cda074\",\n    \"green\": \"#9e744d\",\n    \"yellow\": \"#fecf75\",\n    \"blue\": \"#720102\",\n    \"magenta\": \"#734c4d\",\n    \"cyan\": \"#979797\",\n    \"white\": \"#ffffce\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#fecea0\",\n    \"brightGreen\": \"#cc734d\",\n    \"brightYellow\": \"#fd9f4d\",\n    \"brightBlue\": \"#cb4a05\",\n    \"brightMagenta\": \"#4e739f\",\n    \"brightCyan\": \"#fed04d\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffce\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#4e739f\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jonascarpay\",\n          \"link\": \"https://github.com/jonascarpay\"\n        },\n        {\n          \"name\": \"fcpg\",\n          \"link\": \"https://github.com/fcpg\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Fairyfloss\",\n    \"black\": \"#040303\",\n    \"red\": \"#f92672\",\n    \"green\": \"#c2ffdf\",\n    \"yellow\": \"#e6c000\",\n    \"blue\": \"#c2ffdf\",\n    \"magenta\": \"#ffb8d1\",\n    \"cyan\": \"#c5a3ff\",\n    \"white\": \"#f8f8f0\",\n    \"brightBlack\": \"#6090cb\",\n    \"brightRed\": \"#ff857f\",\n    \"brightGreen\": \"#c2ffdf\",\n    \"brightYellow\": \"#ffea00\",\n    \"brightBlue\": \"#c2ffdf\",\n    \"brightMagenta\": \"#ffb8d1\",\n    \"brightCyan\": \"#c5a3ff\",\n    \"brightWhite\": \"#f8f8f0\",\n    \"background\": \"#5a5475\",\n    \"foreground\": \"#f8f8f2\",\n    \"cursor\": \"#f8f8f0\",\n    \"selection\": \"#8077a8\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Fideloper\",\n    \"black\": \"#292f33\",\n    \"red\": \"#cb1e2d\",\n    \"green\": \"#edb8ac\",\n    \"yellow\": \"#b7ab9b\",\n    \"blue\": \"#2e78c2\",\n    \"magenta\": \"#c0236f\",\n    \"cyan\": \"#309186\",\n    \"white\": \"#eae3ce\",\n    \"brightBlack\": \"#092028\",\n    \"brightRed\": \"#d4605a\",\n    \"brightGreen\": \"#d4605a\",\n    \"brightYellow\": \"#a86671\",\n    \"brightBlue\": \"#7c85c4\",\n    \"brightMagenta\": \"#5c5db2\",\n    \"brightCyan\": \"#819090\",\n    \"brightWhite\": \"#fcf4df\",\n    \"background\": \"#292f33\",\n    \"foreground\": \"#dbdae0\",\n    \"cursor\": \"#d4605a\",\n    \"selection\": \"#efb8ac\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Fideloper\",\n          \"link\": \"http://fideloper.com/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"FirefoxDev\",\n    \"black\": \"#002831\",\n    \"red\": \"#e63853\",\n    \"green\": \"#5eb83c\",\n    \"yellow\": \"#a57706\",\n    \"blue\": \"#359ddf\",\n    \"magenta\": \"#d75cff\",\n    \"cyan\": \"#4b73a2\",\n    \"white\": \"#dcdcdc\",\n    \"brightBlack\": \"#001e27\",\n    \"brightRed\": \"#e1003f\",\n    \"brightGreen\": \"#1d9000\",\n    \"brightYellow\": \"#cd9409\",\n    \"brightBlue\": \"#006fc0\",\n    \"brightMagenta\": \"#a200da\",\n    \"brightCyan\": \"#005794\",\n    \"brightWhite\": \"#e2e2e2\",\n    \"background\": \"#0e1011\",\n    \"foreground\": \"#7c8fa4\",\n    \"cursor\": \"#708284\",\n    \"selection\": \"#163c61\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Or3stis\",\n          \"link\": \"https://github.com/Or3stis\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Firewatch\",\n    \"black\": \"#585f6d\",\n    \"red\": \"#d95360\",\n    \"green\": \"#5ab977\",\n    \"yellow\": \"#dfb563\",\n    \"blue\": \"#4d89c4\",\n    \"magenta\": \"#d55119\",\n    \"cyan\": \"#44a8b6\",\n    \"white\": \"#e6e5ff\",\n    \"brightBlack\": \"#585f6d\",\n    \"brightRed\": \"#d95360\",\n    \"brightGreen\": \"#5ab977\",\n    \"brightYellow\": \"#dfb563\",\n    \"brightBlue\": \"#4c89c5\",\n    \"brightMagenta\": \"#d55119\",\n    \"brightCyan\": \"#44a8b6\",\n    \"brightWhite\": \"#e6e5ff\",\n    \"background\": \"#1e2027\",\n    \"foreground\": \"#9ba2b2\",\n    \"cursor\": \"#f6f7ec\",\n    \"selection\": \"#2f363e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Sebastian Szturo\",\n          \"link\": \"https://github.com/SebastianSzturo\"\n        },\n        {\n          \"name\": \"Ben Styles\",\n          \"link\": \"https://github.com/leeds-ebooks\"\n        },\n        {\n          \"name\": \"Firewatch game\",\n          \"link\": \"http://www.firewatchgame.com/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"FishTank\",\n    \"black\": \"#03073c\",\n    \"red\": \"#c6004a\",\n    \"green\": \"#acf157\",\n    \"yellow\": \"#fecd5e\",\n    \"blue\": \"#525fb8\",\n    \"magenta\": \"#986f82\",\n    \"cyan\": \"#968763\",\n    \"white\": \"#ecf0fc\",\n    \"brightBlack\": \"#6c5b30\",\n    \"brightRed\": \"#da4b8a\",\n    \"brightGreen\": \"#dbffa9\",\n    \"brightYellow\": \"#fee6a9\",\n    \"brightBlue\": \"#b2befa\",\n    \"brightMagenta\": \"#fda5cd\",\n    \"brightCyan\": \"#a5bd86\",\n    \"brightWhite\": \"#f6ffec\",\n    \"background\": \"#232537\",\n    \"foreground\": \"#ecf0fe\",\n    \"cursor\": \"#fecd5e\",\n    \"selection\": \"#fcf7e9\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Flat\",\n    \"black\": \"#222d3f\",\n    \"red\": \"#a82320\",\n    \"green\": \"#32a548\",\n    \"yellow\": \"#e58d11\",\n    \"blue\": \"#3167ac\",\n    \"magenta\": \"#781aa0\",\n    \"cyan\": \"#2c9370\",\n    \"white\": \"#b0b6ba\",\n    \"brightBlack\": \"#212c3c\",\n    \"brightRed\": \"#d4312e\",\n    \"brightGreen\": \"#2d9440\",\n    \"brightYellow\": \"#e5be0c\",\n    \"brightBlue\": \"#3c7dd2\",\n    \"brightMagenta\": \"#8230a7\",\n    \"brightCyan\": \"#35b387\",\n    \"brightWhite\": \"#e7eced\",\n    \"background\": \"#002240\",\n    \"foreground\": \"#2cc55d\",\n    \"cursor\": \"#e5be0c\",\n    \"selection\": \"#792b9c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ahmetsulek\",\n          \"link\": \"https://github.com/ahmetsulek/flat-terminal\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Flatland\",\n    \"black\": \"#1d1d19\",\n    \"red\": \"#f18339\",\n    \"green\": \"#9fd364\",\n    \"yellow\": \"#f4ef6d\",\n    \"blue\": \"#5096be\",\n    \"magenta\": \"#695abc\",\n    \"cyan\": \"#d63865\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#1d1d19\",\n    \"brightRed\": \"#d22a24\",\n    \"brightGreen\": \"#a7d42c\",\n    \"brightYellow\": \"#ff8949\",\n    \"brightBlue\": \"#61b9d0\",\n    \"brightMagenta\": \"#695abc\",\n    \"brightCyan\": \"#d63865\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1d1f21\",\n    \"foreground\": \"#b8dbef\",\n    \"cursor\": \"#708284\",\n    \"selection\": \"#2b2a24\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"realchaseadams\",\n          \"link\": \"http://www.snip2code.com/Snippet/148193/Flatland-color-scheme-for-iTerm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Floraverse\",\n    \"black\": \"#08002e\",\n    \"red\": \"#64002c\",\n    \"green\": \"#5d731a\",\n    \"yellow\": \"#cd751c\",\n    \"blue\": \"#1d6da1\",\n    \"magenta\": \"#b7077e\",\n    \"cyan\": \"#42a38c\",\n    \"white\": \"#f3e0b8\",\n    \"brightBlack\": \"#331e4d\",\n    \"brightRed\": \"#d02063\",\n    \"brightGreen\": \"#b4ce59\",\n    \"brightYellow\": \"#fac357\",\n    \"brightBlue\": \"#40a4cf\",\n    \"brightMagenta\": \"#f12aae\",\n    \"brightCyan\": \"#62caa8\",\n    \"brightWhite\": \"#fff5db\",\n    \"background\": \"#0e0d15\",\n    \"foreground\": \"#dbd1b9\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#f3e0b8\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"papayakitty\",\n          \"link\": \"http://floraverse.com/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"ForestBlue\",\n    \"black\": \"#333333\",\n    \"red\": \"#f8818e\",\n    \"green\": \"#92d3a2\",\n    \"yellow\": \"#1a8e63\",\n    \"blue\": \"#8ed0ce\",\n    \"magenta\": \"#5e468c\",\n    \"cyan\": \"#31658c\",\n    \"white\": \"#e2d8cd\",\n    \"brightBlack\": \"#3d3d3d\",\n    \"brightRed\": \"#fb3d66\",\n    \"brightGreen\": \"#6bb48d\",\n    \"brightYellow\": \"#30c85a\",\n    \"brightBlue\": \"#39a7a2\",\n    \"brightMagenta\": \"#7e62b3\",\n    \"brightCyan\": \"#6096bf\",\n    \"brightWhite\": \"#e2d8cd\",\n    \"background\": \"#051519\",\n    \"foreground\": \"#e2d8cd\",\n    \"cursor\": \"#9e9ecb\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"olkinn\",\n          \"link\": \"https://github.com/olkinn/forest-blue-iTerm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Framer\",\n    \"black\": \"#141414\",\n    \"red\": \"#ff5555\",\n    \"green\": \"#98ec65\",\n    \"yellow\": \"#ffcc33\",\n    \"blue\": \"#00aaff\",\n    \"magenta\": \"#aa88ff\",\n    \"cyan\": \"#88ddff\",\n    \"white\": \"#cccccc\",\n    \"brightBlack\": \"#414141\",\n    \"brightRed\": \"#ff8888\",\n    \"brightGreen\": \"#b6f292\",\n    \"brightYellow\": \"#ffd966\",\n    \"brightBlue\": \"#33bbff\",\n    \"brightMagenta\": \"#cebbff\",\n    \"brightCyan\": \"#bbecff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#111111\",\n    \"foreground\": \"#777777\",\n    \"cursor\": \"#fcdc08\",\n    \"selection\": \"#666666\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"markogresak\",\n          \"link\": \"https://github.com/markogresak\"\n        },\n        {\n          \"name\": \"Framer\",\n          \"link\": \"https://framer.com\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"FrontEndDelight\",\n    \"black\": \"#242526\",\n    \"red\": \"#f8511b\",\n    \"green\": \"#565747\",\n    \"yellow\": \"#fa771d\",\n    \"blue\": \"#2c70b7\",\n    \"magenta\": \"#f02e4f\",\n    \"cyan\": \"#3ca1a6\",\n    \"white\": \"#adadad\",\n    \"brightBlack\": \"#5fac6d\",\n    \"brightRed\": \"#f74319\",\n    \"brightGreen\": \"#74ec4c\",\n    \"brightYellow\": \"#fdc325\",\n    \"brightBlue\": \"#3393ca\",\n    \"brightMagenta\": \"#e75e4f\",\n    \"brightCyan\": \"#4fbce6\",\n    \"brightWhite\": \"#8c735b\",\n    \"background\": \"#1b1c1d\",\n    \"foreground\": \"#adadad\",\n    \"cursor\": \"#cdcdcd\",\n    \"selection\": \"#ea6154\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"FunForrest\",\n    \"black\": \"#000000\",\n    \"red\": \"#d6262b\",\n    \"green\": \"#919c00\",\n    \"yellow\": \"#be8a13\",\n    \"blue\": \"#4699a3\",\n    \"magenta\": \"#8d4331\",\n    \"cyan\": \"#da8213\",\n    \"white\": \"#ddc265\",\n    \"brightBlack\": \"#7f6a55\",\n    \"brightRed\": \"#e55a1c\",\n    \"brightGreen\": \"#bfc65a\",\n    \"brightYellow\": \"#ffcb1b\",\n    \"brightBlue\": \"#7cc9cf\",\n    \"brightMagenta\": \"#d26349\",\n    \"brightCyan\": \"#e6a96b\",\n    \"brightWhite\": \"#ffeaa3\",\n    \"background\": \"#251200\",\n    \"foreground\": \"#dec165\",\n    \"cursor\": \"#e5591c\",\n    \"selection\": \"#e5591c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Galaxy\",\n    \"black\": \"#000000\",\n    \"red\": \"#f9555f\",\n    \"green\": \"#21b089\",\n    \"yellow\": \"#fef02a\",\n    \"blue\": \"#589df6\",\n    \"magenta\": \"#944d95\",\n    \"cyan\": \"#1f9ee7\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#fa8c8f\",\n    \"brightGreen\": \"#35bb9a\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#589df6\",\n    \"brightMagenta\": \"#e75699\",\n    \"brightCyan\": \"#3979bc\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1d2837\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jglovier\",\n          \"link\": \"https://github.com/jglovier/galaxy-theme-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Galizur\",\n    \"black\": \"#223344\",\n    \"red\": \"#aa1122\",\n    \"green\": \"#33aa11\",\n    \"yellow\": \"#ccaa22\",\n    \"blue\": \"#2255cc\",\n    \"magenta\": \"#7755aa\",\n    \"cyan\": \"#22bbdd\",\n    \"white\": \"#8899aa\",\n    \"brightBlack\": \"#556677\",\n    \"brightRed\": \"#ff1133\",\n    \"brightGreen\": \"#33ff11\",\n    \"brightYellow\": \"#ffdd33\",\n    \"brightBlue\": \"#3377ff\",\n    \"brightMagenta\": \"#aa77ff\",\n    \"brightCyan\": \"#33ddff\",\n    \"brightWhite\": \"#bbccdd\",\n    \"background\": \"#071317\",\n    \"foreground\": \"#ddeeff\",\n    \"cursor\": \"#ddeeff\",\n    \"selection\": \"#071317\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Raziel Anarki\",\n          \"link\": \"https://github.com/razielanarki\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Ganyu\",\n    \"cursor\": \"#AC5487\",\n    \"background\": \"#221b2f\",\n    \"foreground\": \"#5055C2\",\n    \"selection\": \"#d7c6a4\",\n    \"black\": \"#12061B\",\n    \"brightBlack\": \"#322a51\",\n    \"blue\": \"#5256c3\",\n    \"brightBlue\": \"#9aa8dd\",\n    \"cyan\": \"#2aadb3\",\n    \"brightCyan\": \"#7ce7d8\",\n    \"green\": \"#c7e18d\",\n    \"brightGreen\": \"#b4f42c\",\n    \"magenta\": \"#ddb2ff\",\n    \"brightMagenta\": \"#9681ed\",\n    \"red\": \"#E06C75\",\n    \"brightRed\": \"#a5313d\",\n    \"white\": \"#ecebea\",\n    \"brightWhite\": \"#f3f3f3\",\n    \"yellow\": \"#f8b433\",\n    \"brightYellow\": \"#f1d661\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"resyfer\",\n          \"link\": \"https://github.com/resyfer\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Github\",\n    \"black\": \"#3e3e3e\",\n    \"red\": \"#970b16\",\n    \"green\": \"#07962a\",\n    \"yellow\": \"#f8eec7\",\n    \"blue\": \"#003e8a\",\n    \"magenta\": \"#e94691\",\n    \"cyan\": \"#89d1ec\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#de0000\",\n    \"brightGreen\": \"#87d5a2\",\n    \"brightYellow\": \"#f1d007\",\n    \"brightBlue\": \"#2e6cba\",\n    \"brightMagenta\": \"#ffa29f\",\n    \"brightCyan\": \"#1cfafe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#f4f4f4\",\n    \"foreground\": \"#3e3e3e\",\n    \"cursor\": \"#3f3f3f\",\n    \"selection\": \"#a9c1e2\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"Github\",\n          \"link\": \"https://github.com/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"GitHub Dark\",\n    \"black\": \"#000000\",\n    \"red\": \"#f78166\",\n    \"green\": \"#56d364\",\n    \"yellow\": \"#e3b341\",\n    \"blue\": \"#6ca4f8\",\n    \"magenta\": \"#db61a2\",\n    \"cyan\": \"#2b7489\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#4d4d4d\",\n    \"brightRed\": \"#f78166\",\n    \"brightGreen\": \"#56d364\",\n    \"brightYellow\": \"#e3b341\",\n    \"brightBlue\": \"#6ca4f8\",\n    \"brightMagenta\": \"#db61a2\",\n    \"brightCyan\": \"#2b7489\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#101216\",\n    \"foreground\": \"#8b949e\",\n    \"cursor\": \"#c9d1d9\",\n    \"selection\": \"#3b5070\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Glacier\",\n    \"black\": \"#2e343c\",\n    \"red\": \"#bd0f2f\",\n    \"green\": \"#35a770\",\n    \"yellow\": \"#fb9435\",\n    \"blue\": \"#1f5872\",\n    \"magenta\": \"#bd2523\",\n    \"cyan\": \"#778397\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#404a55\",\n    \"brightRed\": \"#bd0f2f\",\n    \"brightGreen\": \"#49e998\",\n    \"brightYellow\": \"#fddf6e\",\n    \"brightBlue\": \"#2a8bc1\",\n    \"brightMagenta\": \"#ea4727\",\n    \"brightCyan\": \"#a0b6d3\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0c1115\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#6c6c6c\",\n    \"selection\": \"#bd2523\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"bahlo\",\n          \"link\": \"https://github.com/bahlo/iterm-colors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Glorious\",\n    \"black\": \"#1e1e1e\",\n    \"red\": \"#be0f17\",\n    \"green\": \"#868715\",\n    \"yellow\": \"#cc881a\",\n    \"blue\": \"#16777a\",\n    \"magenta\": \"#a04b73\",\n    \"cyan\": \"#578e57\",\n    \"white\": \"#978771\",\n    \"brightBlack\": \"#7f7061\",\n    \"brightRed\": \"#f73028\",\n    \"brightGreen\": \"#d5d5d7\",\n    \"brightYellow\": \"#f7b125\",\n    \"brightBlue\": \"#4e917c\",\n    \"brightMagenta\": \"#c77089\",\n    \"brightCyan\": \"#7db669\",\n    \"brightWhite\": \"#e6d4a3\",\n    \"background\": \"#201d27\",\n    \"foreground\": \"#c8c8c9\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"alex\",\n          \"link\": \"https://github.com/AlexMailo\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Grape\",\n    \"black\": \"#2d283f\",\n    \"red\": \"#ed2261\",\n    \"green\": \"#1fa91b\",\n    \"yellow\": \"#8ddc20\",\n    \"blue\": \"#487df4\",\n    \"magenta\": \"#8d35c9\",\n    \"cyan\": \"#3bdeed\",\n    \"white\": \"#9e9ea0\",\n    \"brightBlack\": \"#59516a\",\n    \"brightRed\": \"#f0729a\",\n    \"brightGreen\": \"#53aa5e\",\n    \"brightYellow\": \"#b2dc87\",\n    \"brightBlue\": \"#a9bcec\",\n    \"brightMagenta\": \"#ad81c2\",\n    \"brightCyan\": \"#9de3eb\",\n    \"brightWhite\": \"#a288f7\",\n    \"background\": \"#171423\",\n    \"foreground\": \"#9f9fa1\",\n    \"cursor\": \"#a288f7\",\n    \"selection\": \"#493d70\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Grass\",\n    \"black\": \"#000000\",\n    \"red\": \"#bb0000\",\n    \"green\": \"#00bb00\",\n    \"yellow\": \"#e7b000\",\n    \"blue\": \"#0000a3\",\n    \"magenta\": \"#950062\",\n    \"cyan\": \"#00bbbb\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#bb0000\",\n    \"brightGreen\": \"#00bb00\",\n    \"brightYellow\": \"#e7b000\",\n    \"brightBlue\": \"#0000bb\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#13773d\",\n    \"foreground\": \"#fff0a5\",\n    \"cursor\": \"#8c2800\",\n    \"selection\": \"#b64926\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Grey-green\",\n    \"black\": \"#000000\",\n    \"red\": \"#fe1414\",\n    \"green\": \"#74ff00\",\n    \"yellow\": \"#f1ff01\",\n    \"blue\": \"#00deff\",\n    \"magenta\": \"#ff00f0\",\n    \"cyan\": \"#00ffbc\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#ff3939\",\n    \"brightGreen\": \"#00ff44\",\n    \"brightYellow\": \"#ffd100\",\n    \"brightBlue\": \"#00afff\",\n    \"brightMagenta\": \"#ff008a\",\n    \"brightCyan\": \"#00ffd3\",\n    \"brightWhite\": \"#f5ecec\",\n    \"background\": \"#002a1a\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#fff400\",\n    \"selection\": \"#517e50\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Gruvbox Light\",\n    \"black\": \"#fbf1c7\",\n    \"red\": \"#9d0006\",\n    \"green\": \"#79740e\",\n    \"yellow\": \"#b57614\",\n    \"blue\": \"#076678\",\n    \"magenta\": \"#8f3f71\",\n    \"cyan\": \"#427b58\",\n    \"white\": \"#3c3836\",\n    \"brightBlack\": \"#9d8374\",\n    \"brightRed\": \"#cc241d\",\n    \"brightGreen\": \"#98971a\",\n    \"brightYellow\": \"#d79921\",\n    \"brightBlue\": \"#458588\",\n    \"brightMagenta\": \"#b16186\",\n    \"brightCyan\": \"#689d69\",\n    \"brightWhite\": \"#7c6f64\",\n    \"background\": \"#fbf1c7\",\n    \"foreground\": \"#282828\",\n    \"cursor\": \"#282828\",\n    \"selection\": \"#d5c4a1\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"morhetz\",\n          \"link\": \"https://github.com/morhetz\"\n        },\n        {\n          \"name\": \"reynn\",\n          \"link\": \"https://github.com/reynn\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"GruvboxDark\",\n    \"black\": \"#282828\",\n    \"red\": \"#cc241d\",\n    \"green\": \"#98971a\",\n    \"yellow\": \"#d79921\",\n    \"blue\": \"#458588\",\n    \"magenta\": \"#b16286\",\n    \"cyan\": \"#689d6a\",\n    \"white\": \"#a89984\",\n    \"brightBlack\": \"#928374\",\n    \"brightRed\": \"#fb4934\",\n    \"brightGreen\": \"#b8bb26\",\n    \"brightYellow\": \"#fabd2f\",\n    \"brightBlue\": \"#83a598\",\n    \"brightMagenta\": \"#d3869b\",\n    \"brightCyan\": \"#8ec07c\",\n    \"brightWhite\": \"#ebdbb2\",\n    \"background\": \"#282828\",\n    \"foreground\": \"#ebdbb2\",\n    \"cursor\": \"#ebdbb2\",\n    \"selection\": \"#665c54\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"GruvboxDarkHard\",\n    \"black\": \"#1b1b1b\",\n    \"red\": \"#cc241d\",\n    \"green\": \"#98971a\",\n    \"yellow\": \"#d79921\",\n    \"blue\": \"#458588\",\n    \"magenta\": \"#b16286\",\n    \"cyan\": \"#689d6a\",\n    \"white\": \"#a89984\",\n    \"brightBlack\": \"#928374\",\n    \"brightRed\": \"#fb4934\",\n    \"brightGreen\": \"#b8bb26\",\n    \"brightYellow\": \"#fabd2f\",\n    \"brightBlue\": \"#83a598\",\n    \"brightMagenta\": \"#d3869b\",\n    \"brightCyan\": \"#8ec07c\",\n    \"brightWhite\": \"#ebdbb2\",\n    \"background\": \"#1b1b1b\",\n    \"foreground\": \"#ebdbb2\",\n    \"cursor\": \"#ebdbb2\",\n    \"selection\": \"#665c54\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Guezwhoz\",\n    \"black\": \"#080808\",\n    \"red\": \"#ff5f5f\",\n    \"green\": \"#87d7af\",\n    \"yellow\": \"#d7d787\",\n    \"blue\": \"#5fafd7\",\n    \"magenta\": \"#afafff\",\n    \"cyan\": \"#5fd7d7\",\n    \"white\": \"#dadada\",\n    \"brightBlack\": \"#8a8a8a\",\n    \"brightRed\": \"#d75f5f\",\n    \"brightGreen\": \"#afd7af\",\n    \"brightYellow\": \"#d7d7af\",\n    \"brightBlue\": \"#87afd7\",\n    \"brightMagenta\": \"#afafd7\",\n    \"brightCyan\": \"#87d7d7\",\n    \"brightWhite\": \"#dadada\",\n    \"background\": \"#1c1c1c\",\n    \"foreground\": \"#d0d0d0\",\n    \"cursor\": \"#eeeeee\",\n    \"selection\": \"#005f5f\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Egor Lem\",\n          \"link\": \"https://github.com/guesswhozzz/guezwhoz-iterm2-theme\"\n        }\n      ]\n    }\n  },\n  {\n    \"background\": \"#1F1F1E\",\n    \"black\": \"#151507\",\n    \"blue\": \"#839496\",\n    \"brightBlack\": \"#1F1F1E\",\n    \"brightBlue\": \"#839496\",\n    \"brightCyan\": \"#93A1A1\",\n    \"brightGreen\": \"#586E75\",\n    \"brightMagenta\": \"#6C71C4\",\n    \"brightRed\": \"#CB4B16\",\n    \"brightWhite\": \"#FFFFFF\",\n    \"brightYellow\": \"#657B83\",\n    \"cursor\": \"#FFFFFF\",\n    \"cyan\": \"#B0D1BA\",\n    \"foreground\": \"#839496\",\n    \"green\": \"#849900\",\n    \"name\": \"h4rithd\",\n    \"magenta\": \"#D33682\",\n    \"red\": \"#C94B16\",\n    \"selection\": \"#FFFFFF\",\n    \"white\": \"#FFFFFF\",\n    \"yellow\": \"#B58900\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"background\": \"#1E1E1E\",\n    \"black\": \"#010100\",\n    \"blue\": \"#3464A5\",\n    \"brightBlack\": \"#545752\",\n    \"brightBlue\": \"#729ECE\",\n    \"brightCyan\": \"#35E2E3\",\n    \"brightGreen\": \"#8BE235\",\n    \"brightMagenta\": \"#AC7EA8\",\n    \"brightRed\": \"#EE282B\",\n    \"brightWhite\": \"#D3D7CF\",\n    \"brightYellow\": \"#FDE94E\",\n    \"cursor\": \"#FFFFFF\",\n    \"cyan\": \"#06989A\",\n    \"foreground\": \"#FFFEFF\",\n    \"green\": \"#4E9B07\",\n    \"name\": \"h4rithd.com\",\n    \"magenta\": \"#75517A\",\n    \"red\": \"#CC0000\",\n    \"selection\": \"#FFFFFF\",\n    \"white\": \"#D3D7CF\",\n    \"yellow\": \"#C4A000\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Hacktober\",\n    \"black\": \"#191918\",\n    \"red\": \"#b34538\",\n    \"green\": \"#587744\",\n    \"yellow\": \"#d08949\",\n    \"blue\": \"#206ec5\",\n    \"magenta\": \"#864651\",\n    \"cyan\": \"#ac9166\",\n    \"white\": \"#f1eee7\",\n    \"brightBlack\": \"#2c2b2a\",\n    \"brightRed\": \"#b33323\",\n    \"brightGreen\": \"#42824a\",\n    \"brightYellow\": \"#c75a22\",\n    \"brightBlue\": \"#5389c5\",\n    \"brightMagenta\": \"#e795a5\",\n    \"brightCyan\": \"#ebc587\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#141414\",\n    \"foreground\": \"#c9c9c9\",\n    \"cursor\": \"#c9c9c9\",\n    \"selection\": \"#141414\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Hardcore\",\n    \"black\": \"#1b1d1e\",\n    \"red\": \"#f92672\",\n    \"green\": \"#a6e22e\",\n    \"yellow\": \"#fd971f\",\n    \"blue\": \"#66d9ef\",\n    \"magenta\": \"#9e6ffe\",\n    \"cyan\": \"#5e7175\",\n    \"white\": \"#ccccc6\",\n    \"brightBlack\": \"#505354\",\n    \"brightRed\": \"#ff669d\",\n    \"brightGreen\": \"#beed5f\",\n    \"brightYellow\": \"#e6db74\",\n    \"brightBlue\": \"#66d9ef\",\n    \"brightMagenta\": \"#9e6ffe\",\n    \"brightCyan\": \"#a3babf\",\n    \"brightWhite\": \"#f8f8f2\",\n    \"background\": \"#121212\",\n    \"foreground\": \"#a0a0a0\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#453b39\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"hardcore\",\n          \"link\": \"https://github.com/hardcore/iTerm-colors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Harper\",\n    \"black\": \"#010101\",\n    \"red\": \"#f8b63f\",\n    \"green\": \"#7fb5e1\",\n    \"yellow\": \"#d6da25\",\n    \"blue\": \"#489e48\",\n    \"magenta\": \"#b296c6\",\n    \"cyan\": \"#f5bfd7\",\n    \"white\": \"#a8a49d\",\n    \"brightBlack\": \"#726e6a\",\n    \"brightRed\": \"#f8b63f\",\n    \"brightGreen\": \"#7fb5e1\",\n    \"brightYellow\": \"#d6da25\",\n    \"brightBlue\": \"#489e48\",\n    \"brightMagenta\": \"#b296c6\",\n    \"brightCyan\": \"#f5bfd7\",\n    \"brightWhite\": \"#fefbea\",\n    \"background\": \"#010101\",\n    \"foreground\": \"#a8a49d\",\n    \"cursor\": \"#a8a49d\",\n    \"selection\": \"#5a5753\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"idleberg\",\n          \"link\": \"https://github.com/idleberg/Harper-iTerm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"HaX0R_BLUE\",\n    \"black\": \"#010921\",\n    \"red\": \"#10b6ff\",\n    \"green\": \"#10b6ff\",\n    \"yellow\": \"#10b6ff\",\n    \"blue\": \"#10b6ff\",\n    \"magenta\": \"#10b6ff\",\n    \"cyan\": \"#10b6ff\",\n    \"white\": \"#fafafa\",\n    \"brightBlack\": \"#080117\",\n    \"brightRed\": \"#00b3f7\",\n    \"brightGreen\": \"#00b3f7\",\n    \"brightYellow\": \"#00b3f7\",\n    \"brightBlue\": \"#00b3f7\",\n    \"brightMagenta\": \"#00b3f7\",\n    \"brightCyan\": \"#00b3f7\",\n    \"brightWhite\": \"#fefefe\",\n    \"background\": \"#010515\",\n    \"foreground\": \"#11b7ff\",\n    \"cursor\": \"#10b6ff\",\n    \"selection\": \"#c1e4ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"HaX0R_GR33N\",\n    \"black\": \"#001f0b\",\n    \"red\": \"#15d00d\",\n    \"green\": \"#15d00d\",\n    \"yellow\": \"#15d00d\",\n    \"blue\": \"#15d00d\",\n    \"magenta\": \"#15d00d\",\n    \"cyan\": \"#15d00d\",\n    \"white\": \"#fafafa\",\n    \"brightBlack\": \"#001510\",\n    \"brightRed\": \"#19e20e\",\n    \"brightGreen\": \"#19e20e\",\n    \"brightYellow\": \"#19e20e\",\n    \"brightBlue\": \"#19e20e\",\n    \"brightMagenta\": \"#19e20e\",\n    \"brightCyan\": \"#19e20e\",\n    \"brightWhite\": \"#fefefe\",\n    \"background\": \"#020f01\",\n    \"foreground\": \"#16b10e\",\n    \"cursor\": \"#15d00d\",\n    \"selection\": \"#d4ffc1\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"HaX0R_R3D\",\n    \"black\": \"#1f0000\",\n    \"red\": \"#b00d0d\",\n    \"green\": \"#b00d0d\",\n    \"yellow\": \"#b00d0d\",\n    \"blue\": \"#b00d0d\",\n    \"magenta\": \"#b00d0d\",\n    \"cyan\": \"#b00d0d\",\n    \"white\": \"#fafafa\",\n    \"brightBlack\": \"#150000\",\n    \"brightRed\": \"#ff1111\",\n    \"brightGreen\": \"#ff1010\",\n    \"brightYellow\": \"#ff1010\",\n    \"brightBlue\": \"#ff1010\",\n    \"brightMagenta\": \"#ff1010\",\n    \"brightCyan\": \"#ff1010\",\n    \"brightWhite\": \"#fefefe\",\n    \"background\": \"#200101\",\n    \"foreground\": \"#b10e0e\",\n    \"cursor\": \"#b00d0d\",\n    \"selection\": \"#ebc1ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Highway\",\n    \"black\": \"#000000\",\n    \"red\": \"#d00e18\",\n    \"green\": \"#138034\",\n    \"yellow\": \"#ffcb3e\",\n    \"blue\": \"#006bb3\",\n    \"magenta\": \"#6b2775\",\n    \"cyan\": \"#384564\",\n    \"white\": \"#ededed\",\n    \"brightBlack\": \"#5d504a\",\n    \"brightRed\": \"#f07e18\",\n    \"brightGreen\": \"#b1d130\",\n    \"brightYellow\": \"#fff120\",\n    \"brightBlue\": \"#4fc2fd\",\n    \"brightMagenta\": \"#de0071\",\n    \"brightCyan\": \"#5d504a\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#222225\",\n    \"foreground\": \"#ededed\",\n    \"cursor\": \"#e0d9b9\",\n    \"selection\": \"#384564\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Hipster Green\",\n    \"black\": \"#000000\",\n    \"red\": \"#b6214a\",\n    \"green\": \"#00a600\",\n    \"yellow\": \"#bfbf00\",\n    \"blue\": \"#246eb2\",\n    \"magenta\": \"#b200b2\",\n    \"cyan\": \"#00a6b2\",\n    \"white\": \"#bfbfbf\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#e50000\",\n    \"brightGreen\": \"#86a93e\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#00e5e5\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#100b05\",\n    \"foreground\": \"#84c138\",\n    \"cursor\": \"#23ff18\",\n    \"selection\": \"#083905\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Unkulunkulu\",\n          \"link\": \"https://github.com/Unkulunkulu\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Hivacruz\",\n    \"black\": \"#202746\",\n    \"red\": \"#c94922\",\n    \"green\": \"#ac9739\",\n    \"yellow\": \"#c08b30\",\n    \"blue\": \"#3d8fd1\",\n    \"magenta\": \"#6679cc\",\n    \"cyan\": \"#22a2c9\",\n    \"white\": \"#979db4\",\n    \"brightBlack\": \"#6b7394\",\n    \"brightRed\": \"#c76b29\",\n    \"brightGreen\": \"#73ad43\",\n    \"brightYellow\": \"#5e6687\",\n    \"brightBlue\": \"#898ea4\",\n    \"brightMagenta\": \"#dfe2f1\",\n    \"brightCyan\": \"#9c637a\",\n    \"brightWhite\": \"#f5f7ff\",\n    \"background\": \"#132638\",\n    \"foreground\": \"#ede4e4\",\n    \"cursor\": \"#979db4\",\n    \"selection\": \"#5e6687\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Yann Defretin\",\n          \"link\": \"https://github.com/kinoute/hivacruz-itermcolors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Homebrew\",\n    \"black\": \"#000000\",\n    \"red\": \"#990000\",\n    \"green\": \"#00a600\",\n    \"yellow\": \"#999900\",\n    \"blue\": \"#0000b2\",\n    \"magenta\": \"#b200b2\",\n    \"cyan\": \"#00a6b2\",\n    \"white\": \"#bfbfbf\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#e50000\",\n    \"brightGreen\": \"#00d900\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#00e5e5\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#00ff00\",\n    \"cursor\": \"#23ff18\",\n    \"selection\": \"#083905\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Hopscotch\",\n    \"black\": \"#322931\",\n    \"red\": \"#dd464c\",\n    \"green\": \"#8fc13e\",\n    \"yellow\": \"#fdcc59\",\n    \"blue\": \"#1290bf\",\n    \"magenta\": \"#c85e7c\",\n    \"cyan\": \"#149b93\",\n    \"white\": \"#b9b5b8\",\n    \"brightBlack\": \"#797379\",\n    \"brightRed\": \"#fd8b19\",\n    \"brightGreen\": \"#433b42\",\n    \"brightYellow\": \"#5c545b\",\n    \"brightBlue\": \"#989498\",\n    \"brightMagenta\": \"#d5d3d5\",\n    \"brightCyan\": \"#b33508\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#322931\",\n    \"foreground\": \"#b9b5b8\",\n    \"cursor\": \"#b9b5b8\",\n    \"selection\": \"#5c545b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Jan T. Sott\",\n          \"link\": \"https://github.com/idleberg/Hopscotch\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Hopscotch.256\",\n    \"black\": \"#322931\",\n    \"red\": \"#dd464c\",\n    \"green\": \"#8fc13e\",\n    \"yellow\": \"#fdcc59\",\n    \"blue\": \"#1290bf\",\n    \"magenta\": \"#c85e7c\",\n    \"cyan\": \"#149b93\",\n    \"white\": \"#b9b5b8\",\n    \"brightBlack\": \"#797379\",\n    \"brightRed\": \"#dd464c\",\n    \"brightGreen\": \"#8fc13e\",\n    \"brightYellow\": \"#fdcc59\",\n    \"brightBlue\": \"#1290bf\",\n    \"brightMagenta\": \"#c85e7c\",\n    \"brightCyan\": \"#149b93\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#322931\",\n    \"foreground\": \"#b9b5b8\",\n    \"cursor\": \"#b9b5b8\",\n    \"selection\": \"#5c545b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Jan T. Sott\",\n          \"link\": \"https://github.com/idleberg/Hopscotch\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Horizon\",\n    \"black\": \"#0a0a0d\",\n    \"red\": \"#E95678\",\n    \"green\": \"#29D398\",\n    \"yellow\": \"#FAB795\",\n    \"blue\": \"#26BBD9\",\n    \"magenta\": \"#EE64AC\",\n    \"cyan\": \"#59E1E3\",\n    \"white\": \"#e5e5e5\",\n    \"brightBlack\": \"#848484\",\n    \"brightRed\": \"#EC6A88\",\n    \"brightGreen\": \"#3FDAA4\",\n    \"brightYellow\": \"#FBC3A7\",\n    \"brightBlue\": \"#3FC4DE\",\n    \"brightMagenta\": \"#F075B5\",\n    \"brightCyan\": \"#6BE4E6\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#1c1e26\",\n    \"foreground\": \"#bdc0c2\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"wafelack\",\n          \"link\": \"https://github.com/wafelack\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Hurtado\",\n    \"black\": \"#575757\",\n    \"red\": \"#ff1b00\",\n    \"green\": \"#a5e055\",\n    \"yellow\": \"#fbe74a\",\n    \"blue\": \"#496487\",\n    \"magenta\": \"#fd5ff1\",\n    \"cyan\": \"#86e9fe\",\n    \"white\": \"#cbcccb\",\n    \"brightBlack\": \"#262626\",\n    \"brightRed\": \"#d51d00\",\n    \"brightGreen\": \"#a5df55\",\n    \"brightYellow\": \"#fbe84a\",\n    \"brightBlue\": \"#89beff\",\n    \"brightMagenta\": \"#c001c1\",\n    \"brightCyan\": \"#86eafe\",\n    \"brightWhite\": \"#dbdbdb\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#dbdbdb\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"juanghurtado\",\n          \"link\": \"https://github.com/juanghurtado/dotfiles\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Hybrid\",\n    \"black\": \"#2a2e33\",\n    \"red\": \"#b84d51\",\n    \"green\": \"#b3bf5a\",\n    \"yellow\": \"#e4b55e\",\n    \"blue\": \"#6e90b0\",\n    \"magenta\": \"#a17eac\",\n    \"cyan\": \"#7fbfb4\",\n    \"white\": \"#b5b9b6\",\n    \"brightBlack\": \"#1d1f22\",\n    \"brightRed\": \"#8d2e32\",\n    \"brightGreen\": \"#798431\",\n    \"brightYellow\": \"#e58a50\",\n    \"brightBlue\": \"#4b6b88\",\n    \"brightMagenta\": \"#6e5079\",\n    \"brightCyan\": \"#4d7b74\",\n    \"brightWhite\": \"#5a626a\",\n    \"background\": \"#161719\",\n    \"foreground\": \"#b7bcba\",\n    \"cursor\": \"#b7bcba\",\n    \"selection\": \"#1e1f22\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"luan\",\n          \"link\": \"https://gist.github.com/luan/6362811\"\n        }\n      ]\n    }\n  },\n  {\n    \"background\": \"#000000\",\n    \"black\": \"#000000\",\n    \"blue\": \"#0066FF\",\n    \"brightBlack\": \"#808080\",\n    \"brightBlue\": \"#0066FF\",\n    \"brightCyan\": \"#00FFFF\",\n    \"brightGreen\": \"#33FF00\",\n    \"brightMagenta\": \"#CC00FF\",\n    \"brightRed\": \"#FE0100\",\n    \"brightWhite\": \"#FFFFFF\",\n    \"brightYellow\": \"#FEFF00\",\n    \"cursor\": \"#FFFFFF\",\n    \"cyan\": \"#00FFFF\",\n    \"foreground\": \"#FFFFFF\",\n    \"green\": \"#33FF00\",\n    \"name\": \"Hyper\",\n    \"magenta\": \"#CC00FF\",\n    \"red\": \"#FE0100\",\n    \"selection\": \"#F81CE5\",\n    \"white\": \"#D0D0D0\",\n    \"yellow\": \"#FEFF00\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"shivang\",\n          \"link\": \"https://github.com/ShivangMathur1\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"iceberg-dark\",\n    \"black\": \"#1e2132\",\n    \"red\": \"#e27878\",\n    \"green\": \"#b4be82\",\n    \"yellow\": \"#e2a478\",\n    \"blue\": \"#84a0c6\",\n    \"magenta\": \"#a093c7\",\n    \"cyan\": \"#89b8c2\",\n    \"white\": \"#c6c8d1\",\n    \"brightBlack\": \"#6b7089\",\n    \"brightRed\": \"#e98989\",\n    \"brightGreen\": \"#c0ca8e\",\n    \"brightYellow\": \"#e9b189\",\n    \"brightBlue\": \"#91acd1\",\n    \"brightMagenta\": \"#ada0d3\",\n    \"brightCyan\": \"#95c4ce\",\n    \"brightWhite\": \"#d2d4de\",\n    \"background\": \"#161821\",\n    \"foreground\": \"#c6c8d1\",\n    \"cursor\": \"#c6c8d1\",\n    \"selection\": \"#c6c8d1\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"cocopon\",\n          \"link\": \"https://github.com/cocopon/iceberg.vim\"\n        },\n        {\n          \"name\": \"pbnj\",\n          \"link\": \"https://github.com/pbnj\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"iceberg-light\",\n    \"black\": \"#dcdfe7\",\n    \"red\": \"#cc517a\",\n    \"green\": \"#668e3d\",\n    \"yellow\": \"#c57339\",\n    \"blue\": \"#2d539e\",\n    \"magenta\": \"#7759b4\",\n    \"cyan\": \"#3f83a6\",\n    \"white\": \"#33374c\",\n    \"brightBlack\": \"#8389a3\",\n    \"brightRed\": \"#cc3768\",\n    \"brightGreen\": \"#598030\",\n    \"brightYellow\": \"#b6662d\",\n    \"brightBlue\": \"#22478e\",\n    \"brightMagenta\": \"#6845ad\",\n    \"brightCyan\": \"#327698\",\n    \"brightWhite\": \"#262a3f\",\n    \"background\": \"#e8e9ec\",\n    \"foreground\": \"#33374c\",\n    \"cursor\": \"#33374c\",\n    \"selection\": \"#33374c\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"cocopon\",\n          \"link\": \"https://github.com/cocopon/iceberg.vim\"\n        },\n        {\n          \"name\": \"pbnj\",\n          \"link\": \"https://github.com/pbnj\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"IC_Green_PPL\",\n    \"black\": \"#014401\",\n    \"red\": \"#ff2736\",\n    \"green\": \"#41a638\",\n    \"yellow\": \"#76a831\",\n    \"blue\": \"#2ec3b9\",\n    \"magenta\": \"#50a096\",\n    \"cyan\": \"#3ca078\",\n    \"white\": \"#e6fef2\",\n    \"brightBlack\": \"#035c03\",\n    \"brightRed\": \"#b4fa5c\",\n    \"brightGreen\": \"#aefb86\",\n    \"brightYellow\": \"#dafa87\",\n    \"brightBlue\": \"#2efaeb\",\n    \"brightMagenta\": \"#50fafa\",\n    \"brightCyan\": \"#3cfac8\",\n    \"brightWhite\": \"#e0f1dc\",\n    \"background\": \"#2c2c2c\",\n    \"foreground\": \"#e0f1dc\",\n    \"cursor\": \"#47fa6b\",\n    \"selection\": \"#116b41\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"IC_Orange_PPL\",\n    \"black\": \"#000000\",\n    \"red\": \"#c13900\",\n    \"green\": \"#a4a900\",\n    \"yellow\": \"#caaf00\",\n    \"blue\": \"#bd6d00\",\n    \"magenta\": \"#fc5e00\",\n    \"cyan\": \"#f79500\",\n    \"white\": \"#ffc88a\",\n    \"brightBlack\": \"#6a4f2a\",\n    \"brightRed\": \"#ff8c68\",\n    \"brightGreen\": \"#f6ff40\",\n    \"brightYellow\": \"#ffe36e\",\n    \"brightBlue\": \"#ffbe55\",\n    \"brightMagenta\": \"#fc874f\",\n    \"brightCyan\": \"#c69752\",\n    \"brightWhite\": \"#fafaff\",\n    \"background\": \"#262626\",\n    \"foreground\": \"#ffcb83\",\n    \"cursor\": \"#fc531d\",\n    \"selection\": \"#c14020\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"idea\",\n    \"black\": \"#adadad\",\n    \"red\": \"#fc5256\",\n    \"green\": \"#98b61c\",\n    \"yellow\": \"#ccb444\",\n    \"blue\": \"#437ee7\",\n    \"magenta\": \"#9d74b0\",\n    \"cyan\": \"#248887\",\n    \"white\": \"#181818\",\n    \"brightBlack\": \"#ffffff\",\n    \"brightRed\": \"#fc7072\",\n    \"brightGreen\": \"#98b61c\",\n    \"brightYellow\": \"#ffff0b\",\n    \"brightBlue\": \"#6c9ced\",\n    \"brightMagenta\": \"#fc7eff\",\n    \"brightCyan\": \"#248887\",\n    \"brightWhite\": \"#181818\",\n    \"background\": \"#202020\",\n    \"foreground\": \"#adadad\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#44475a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"idleToes\",\n    \"black\": \"#323232\",\n    \"red\": \"#d25252\",\n    \"green\": \"#7fe173\",\n    \"yellow\": \"#ffc66d\",\n    \"blue\": \"#4099ff\",\n    \"magenta\": \"#f680ff\",\n    \"cyan\": \"#bed6ff\",\n    \"white\": \"#eeeeec\",\n    \"brightBlack\": \"#535353\",\n    \"brightRed\": \"#f07070\",\n    \"brightGreen\": \"#9dff91\",\n    \"brightYellow\": \"#ffe48b\",\n    \"brightBlue\": \"#5eb7f7\",\n    \"brightMagenta\": \"#ff9dff\",\n    \"brightCyan\": \"#dcf4ff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#323232\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#d6d6d6\",\n    \"selection\": \"#5b5b5b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"idleFingers\",\n          \"link\": \"http://www.idlefingers.co.uk/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"IR_Black\",\n    \"black\": \"#4f4f4f\",\n    \"red\": \"#fa6c60\",\n    \"green\": \"#a8ff60\",\n    \"yellow\": \"#fffeb7\",\n    \"blue\": \"#96cafe\",\n    \"magenta\": \"#fa73fd\",\n    \"cyan\": \"#c6c5fe\",\n    \"white\": \"#efedef\",\n    \"brightBlack\": \"#7b7b7b\",\n    \"brightRed\": \"#fcb6b0\",\n    \"brightGreen\": \"#cfffab\",\n    \"brightYellow\": \"#ffffcc\",\n    \"brightBlue\": \"#b5dcff\",\n    \"brightMagenta\": \"#fb9cfe\",\n    \"brightCyan\": \"#e0e0fe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#f1f1f1\",\n    \"cursor\": \"#808080\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"meqif\",\n          \"link\": \"https://gist.github.com/meqif/1238378\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"iTerm2 Dark Background\",\n    \"black\": \"#000000\",\n    \"red\": \"#c91b00\",\n    \"green\": \"#00c200\",\n    \"yellow\": \"#c7c400\",\n    \"blue\": \"#0225c7\",\n    \"magenta\": \"#ca30c7\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff6e67\",\n    \"brightGreen\": \"#5ffa68\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#ff77ff\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#c7c7c7\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Default\",\n    \"black\": \"#000000\",\n    \"red\": \"#c91b00\",\n    \"green\": \"#00c200\",\n    \"yellow\": \"#c7c400\",\n    \"blue\": \"#2225c4\",\n    \"magenta\": \"#ca30c7\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff6e67\",\n    \"brightGreen\": \"#5ffa68\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#ff77ff\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#e5e5e5\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Light Background\",\n    \"black\": \"#000000\",\n    \"red\": \"#c91b00\",\n    \"green\": \"#00c200\",\n    \"yellow\": \"#c7c400\",\n    \"blue\": \"#0225c7\",\n    \"magenta\": \"#ca30c7\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff6e67\",\n    \"brightGreen\": \"#5ffa68\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#ff77ff\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Pastel Dark Background\",\n    \"black\": \"#626262\",\n    \"red\": \"#ff8373\",\n    \"green\": \"#b4fb73\",\n    \"yellow\": \"#fffdc3\",\n    \"blue\": \"#a5d5fe\",\n    \"magenta\": \"#ff90fe\",\n    \"cyan\": \"#d1d1fe\",\n    \"white\": \"#f1f1f1\",\n    \"brightBlack\": \"#8f8f8f\",\n    \"brightRed\": \"#ffc4be\",\n    \"brightGreen\": \"#d6fcba\",\n    \"brightYellow\": \"#fffed5\",\n    \"brightBlue\": \"#c2e3ff\",\n    \"brightMagenta\": \"#ffb2fe\",\n    \"brightCyan\": \"#e6e6fe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#c7c7c7\",\n    \"cursor\": \"#ffb473\",\n    \"selection\": \"#454d96\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Smoooooth\",\n    \"black\": \"#14191e\",\n    \"red\": \"#b43c2a\",\n    \"green\": \"#00c200\",\n    \"yellow\": \"#c7c400\",\n    \"blue\": \"#2744c7\",\n    \"magenta\": \"#c040be\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#dd7975\",\n    \"brightGreen\": \"#58e790\",\n    \"brightYellow\": \"#ece100\",\n    \"brightBlue\": \"#a7abf2\",\n    \"brightMagenta\": \"#e17ee1\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#15191f\",\n    \"foreground\": \"#dcdcdc\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#b3d7ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Solarized Dark\",\n    \"black\": \"#073642\",\n    \"red\": \"#dc322f\",\n    \"green\": \"#859900\",\n    \"yellow\": \"#b58900\",\n    \"blue\": \"#268bd2\",\n    \"magenta\": \"#d33682\",\n    \"cyan\": \"#2aa198\",\n    \"white\": \"#eee8d5\",\n    \"brightBlack\": \"#002b36\",\n    \"brightRed\": \"#cb4b16\",\n    \"brightGreen\": \"#586e75\",\n    \"brightYellow\": \"#657b83\",\n    \"brightBlue\": \"#839496\",\n    \"brightMagenta\": \"#6c71c4\",\n    \"brightCyan\": \"#93a1a1\",\n    \"brightWhite\": \"#fdf6e3\",\n    \"background\": \"#002b36\",\n    \"foreground\": \"#839496\",\n    \"cursor\": \"#839496\",\n    \"selection\": \"#073642\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Solarized Light\",\n    \"black\": \"#073642\",\n    \"red\": \"#dc322f\",\n    \"green\": \"#859900\",\n    \"yellow\": \"#b58900\",\n    \"blue\": \"#268bd2\",\n    \"magenta\": \"#d33682\",\n    \"cyan\": \"#2aa198\",\n    \"white\": \"#eee8d5\",\n    \"brightBlack\": \"#002b36\",\n    \"brightRed\": \"#cb4b16\",\n    \"brightGreen\": \"#586e75\",\n    \"brightYellow\": \"#657b83\",\n    \"brightBlue\": \"#839496\",\n    \"brightMagenta\": \"#6c71c4\",\n    \"brightCyan\": \"#93a1a1\",\n    \"brightWhite\": \"#fdf6e3\",\n    \"background\": \"#fdf6e3\",\n    \"foreground\": \"#657b83\",\n    \"cursor\": \"#657b83\",\n    \"selection\": \"#eee8d5\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Tango Dark\",\n    \"black\": \"#000000\",\n    \"red\": \"#d81e00\",\n    \"green\": \"#5ea702\",\n    \"yellow\": \"#cfae00\",\n    \"blue\": \"#427ab3\",\n    \"magenta\": \"#89658e\",\n    \"cyan\": \"#00a7aa\",\n    \"white\": \"#dbded8\",\n    \"brightBlack\": \"#686a66\",\n    \"brightRed\": \"#f54235\",\n    \"brightGreen\": \"#99e343\",\n    \"brightYellow\": \"#fdeb61\",\n    \"brightBlue\": \"#84b0d8\",\n    \"brightMagenta\": \"#bc94b7\",\n    \"brightCyan\": \"#37e6e8\",\n    \"brightWhite\": \"#f1f1f0\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"iTerm2 Tango Light\",\n    \"black\": \"#000000\",\n    \"red\": \"#d81e00\",\n    \"green\": \"#5ea702\",\n    \"yellow\": \"#cfae00\",\n    \"blue\": \"#427ab3\",\n    \"magenta\": \"#89658e\",\n    \"cyan\": \"#00a7aa\",\n    \"white\": \"#dbded8\",\n    \"brightBlack\": \"#686a66\",\n    \"brightRed\": \"#f54235\",\n    \"brightGreen\": \"#99e343\",\n    \"brightYellow\": \"#fdeb61\",\n    \"brightBlue\": \"#84b0d8\",\n    \"brightMagenta\": \"#bc94b7\",\n    \"brightCyan\": \"#37e6e8\",\n    \"brightWhite\": \"#f1f1f0\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Jackie Brown\",\n    \"black\": \"#2c1d16\",\n    \"red\": \"#ef5734\",\n    \"green\": \"#2baf2b\",\n    \"yellow\": \"#bebf00\",\n    \"blue\": \"#246eb2\",\n    \"magenta\": \"#d05ec1\",\n    \"cyan\": \"#00acee\",\n    \"white\": \"#bfbfbf\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#e50000\",\n    \"brightGreen\": \"#86a93e\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#00e5e5\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#2c1d16\",\n    \"foreground\": \"#ffcc2f\",\n    \"cursor\": \"#23ff18\",\n    \"selection\": \"#af8d21\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Unkulunkulu\",\n          \"link\": \"https://github.com/Unkulunkulu\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Japanesque\",\n    \"black\": \"#343935\",\n    \"red\": \"#cf3f61\",\n    \"green\": \"#7bb75b\",\n    \"yellow\": \"#e9b32a\",\n    \"blue\": \"#4c9ad4\",\n    \"magenta\": \"#a57fc4\",\n    \"cyan\": \"#389aad\",\n    \"white\": \"#fafaf6\",\n    \"brightBlack\": \"#595b59\",\n    \"brightRed\": \"#d18fa6\",\n    \"brightGreen\": \"#767f2c\",\n    \"brightYellow\": \"#78592f\",\n    \"brightBlue\": \"#135979\",\n    \"brightMagenta\": \"#604291\",\n    \"brightCyan\": \"#76bbca\",\n    \"brightWhite\": \"#b2b5ae\",\n    \"background\": \"#1e1e1e\",\n    \"foreground\": \"#f7f6ec\",\n    \"cursor\": \"#edcf4f\",\n    \"selection\": \"#175877\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"aereal\",\n          \"link\": \"https://github.com/aereal/dotfiles/blob/master/colors/Japanesque/Japanesque.itermcolors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Jellybeans\",\n    \"black\": \"#929292\",\n    \"red\": \"#e27373\",\n    \"green\": \"#94b979\",\n    \"yellow\": \"#ffba7b\",\n    \"blue\": \"#97bedc\",\n    \"magenta\": \"#e1c0fa\",\n    \"cyan\": \"#00988e\",\n    \"white\": \"#dedede\",\n    \"brightBlack\": \"#bdbdbd\",\n    \"brightRed\": \"#ffa1a1\",\n    \"brightGreen\": \"#bddeab\",\n    \"brightYellow\": \"#ffdca0\",\n    \"brightBlue\": \"#b1d8f6\",\n    \"brightMagenta\": \"#fbdaff\",\n    \"brightCyan\": \"#1ab2a8\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#121212\",\n    \"foreground\": \"#dedede\",\n    \"cursor\": \"#ffa560\",\n    \"selection\": \"#474e91\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"qtpi\",\n          \"link\": \"https://github.com/qtpi/Jellybeans.itermcolors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"JetBrains Darcula\",\n    \"black\": \"#000000\",\n    \"red\": \"#fa5355\",\n    \"green\": \"#126e00\",\n    \"yellow\": \"#c2c300\",\n    \"blue\": \"#4581eb\",\n    \"magenta\": \"#fa54ff\",\n    \"cyan\": \"#33c2c1\",\n    \"white\": \"#adadad\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#fb7172\",\n    \"brightGreen\": \"#67ff4f\",\n    \"brightYellow\": \"#ffff00\",\n    \"brightBlue\": \"#6d9df1\",\n    \"brightMagenta\": \"#fb82ff\",\n    \"brightCyan\": \"#60d3d1\",\n    \"brightWhite\": \"#eeeeee\",\n    \"background\": \"#202020\",\n    \"foreground\": \"#adadad\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#1a3272\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vitstr\",\n          \"link\": \"https://github.com/vitstr\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"jubi\",\n    \"black\": \"#3b3750\",\n    \"red\": \"#cf7b98\",\n    \"green\": \"#90a94b\",\n    \"yellow\": \"#6ebfc0\",\n    \"blue\": \"#576ea6\",\n    \"magenta\": \"#bc4f68\",\n    \"cyan\": \"#75a7d2\",\n    \"white\": \"#c3d3de\",\n    \"brightBlack\": \"#a874ce\",\n    \"brightRed\": \"#de90ab\",\n    \"brightGreen\": \"#bcdd61\",\n    \"brightYellow\": \"#87e9ea\",\n    \"brightBlue\": \"#8c9fcd\",\n    \"brightMagenta\": \"#e16c87\",\n    \"brightCyan\": \"#b7c9ef\",\n    \"brightWhite\": \"#d5e5f1\",\n    \"background\": \"#262b33\",\n    \"foreground\": \"#c3d3de\",\n    \"cursor\": \"#c3d3de\",\n    \"selection\": \"#5b5184\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Julia Tretel\",\n          \"link\": \"https://github.com/jutretel\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Juicy Colors\",\n    \"cursor\": \"#FFFFFF\",\n    \"selection\": \"#FFFFFF\",\n    \"background\": \"#292a24\",\n    \"foreground\": \"#CCCCCC\",\n    \"black\": \"#292a24\",\n    \"blue\": \"#209DE5\",\n    \"cyan\": \"#00D2FF\",\n    \"green\": \"#68D644\",\n    \"magenta\": \"#AF80FF\",\n    \"red\": \"#FF6249\",\n    \"white\": \"#CCCCCC\",\n    \"yellow\": \"#FCC223\",\n    \"brightBlack\": \"#808080\",\n    \"brightBlue\": \"#209DE5\",\n    \"brightCyan\": \"#00D2FF\",\n    \"brightGreen\": \"#68D644\",\n    \"brightMagenta\": \"#AF80FF\",\n    \"brightRed\": \"#FF6249\",\n    \"brightWhite\": \"#F2F2F2\",\n    \"brightYellow\": \"#FCC223\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Kanagawa\",\n    \"cursor\": \"#DCD7BA\",\n    \"selection\": \"#2A2A37\",\n    \"background\": \"#1F1F28\",\n    \"foreground\": \"#DCD7BA\",\n    \"black\": \"#1F1F28\",\n    \"blue\": \"#658594\",\n    \"cyan\": \"#9CABCA\",\n    \"green\": \"#76946A\",\n    \"magenta\": \"#957FB8\",\n    \"red\": \"#E82424\",\n    \"white\": \"#DCD7BA\",\n    \"yellow\": \"#FF9E3B\",\n    \"brightBlack\": \"#2A2A37\",\n    \"brightBlue\": \"#7FB4CA\",\n    \"brightCyan\": \"#A3D4D5\",\n    \"brightGreen\": \"#98BB6C\",\n    \"brightMagenta\": \"#D27E99\",\n    \"brightRed\": \"#FF5D62\",\n    \"brightWhite\": \"#DCD7BA\",\n    \"brightYellow\": \"#E6C384\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"kanagawabones\",\n    \"black\": \"#1f1f28\",\n    \"red\": \"#e46a78\",\n    \"green\": \"#98bc6d\",\n    \"yellow\": \"#e5c283\",\n    \"blue\": \"#7eb3c9\",\n    \"magenta\": \"#957fb8\",\n    \"cyan\": \"#7eb3c9\",\n    \"white\": \"#ddd8bb\",\n    \"brightBlack\": \"#3c3c51\",\n    \"brightRed\": \"#ec818c\",\n    \"brightGreen\": \"#9ec967\",\n    \"brightYellow\": \"#f1c982\",\n    \"brightBlue\": \"#7bc2df\",\n    \"brightMagenta\": \"#a98fd2\",\n    \"brightCyan\": \"#7bc2df\",\n    \"brightWhite\": \"#a8a48d\",\n    \"background\": \"#1f1f28\",\n    \"foreground\": \"#ddd8bb\",\n    \"cursor\": \"#e6e0c2\",\n    \"selection\": \"#49473e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Kibble\",\n    \"black\": \"#4d4d4d\",\n    \"red\": \"#c70031\",\n    \"green\": \"#29cf13\",\n    \"yellow\": \"#d8e30e\",\n    \"blue\": \"#3449d1\",\n    \"magenta\": \"#8400ff\",\n    \"cyan\": \"#0798ab\",\n    \"white\": \"#e2d1e3\",\n    \"brightBlack\": \"#5a5a5a\",\n    \"brightRed\": \"#f01578\",\n    \"brightGreen\": \"#6ce05c\",\n    \"brightYellow\": \"#f3f79e\",\n    \"brightBlue\": \"#97a4f7\",\n    \"brightMagenta\": \"#c495f0\",\n    \"brightCyan\": \"#68f2e0\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0e100a\",\n    \"foreground\": \"#f7f7f7\",\n    \"cursor\": \"#9fda9c\",\n    \"selection\": \"#9ba787\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Kolorit\",\n    \"black\": \"#1d1a1e\",\n    \"red\": \"#ff5b82\",\n    \"green\": \"#47d7a1\",\n    \"yellow\": \"#e8e562\",\n    \"blue\": \"#5db4ee\",\n    \"magenta\": \"#da6cda\",\n    \"cyan\": \"#57e9eb\",\n    \"white\": \"#ededed\",\n    \"brightBlack\": \"#1d1a1e\",\n    \"brightRed\": \"#ff5b82\",\n    \"brightGreen\": \"#47d7a1\",\n    \"brightYellow\": \"#e8e562\",\n    \"brightBlue\": \"#5db4ee\",\n    \"brightMagenta\": \"#da6cda\",\n    \"brightCyan\": \"#57e9eb\",\n    \"brightWhite\": \"#ededed\",\n    \"background\": \"#1d1a1e\",\n    \"foreground\": \"#efecec\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#e1925c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"thomaspaulmann\",\n          \"link\": \"https://github.com/thomaspaulmann\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Konsolas\",\n    \"black\": \"#000000\",\n    \"red\": \"#aa1717\",\n    \"green\": \"#18b218\",\n    \"yellow\": \"#ebae1f\",\n    \"blue\": \"#2323a5\",\n    \"magenta\": \"#ad1edc\",\n    \"cyan\": \"#42b0c8\",\n    \"white\": \"#c8c1c1\",\n    \"brightBlack\": \"#7b716e\",\n    \"brightRed\": \"#ff4141\",\n    \"brightGreen\": \"#5fff5f\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#4b4bff\",\n    \"brightMagenta\": \"#ff54ff\",\n    \"brightCyan\": \"#69ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#060606\",\n    \"foreground\": \"#c8c1c1\",\n    \"cursor\": \"#c8c1c1\",\n    \"selection\": \"#060606\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Lab Fox\",\n    \"black\": \"#2e2e2e\",\n    \"red\": \"#fc6d26\",\n    \"green\": \"#3eb383\",\n    \"yellow\": \"#fca121\",\n    \"blue\": \"#db3b21\",\n    \"magenta\": \"#380d75\",\n    \"cyan\": \"#6e49cb\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#464646\",\n    \"brightRed\": \"#ff6517\",\n    \"brightGreen\": \"#53eaa8\",\n    \"brightYellow\": \"#fca013\",\n    \"brightBlue\": \"#db501f\",\n    \"brightMagenta\": \"#441090\",\n    \"brightCyan\": \"#7d53e7\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#2e2e2e\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#7f7f7f\",\n    \"selection\": \"#cb392e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"theatlasroom\",\n          \"link\": \"https://github.com/theatlasroom\"\n        },\n        {\n          \"name\": \"Gitlab design system\",\n          \"link\": \"https://design.gitlab.com\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Laser\",\n    \"black\": \"#626262\",\n    \"red\": \"#ff8373\",\n    \"green\": \"#b4fb73\",\n    \"yellow\": \"#09b4bd\",\n    \"blue\": \"#fed300\",\n    \"magenta\": \"#ff90fe\",\n    \"cyan\": \"#d1d1fe\",\n    \"white\": \"#f1f1f1\",\n    \"brightBlack\": \"#8f8f8f\",\n    \"brightRed\": \"#ffc4be\",\n    \"brightGreen\": \"#d6fcba\",\n    \"brightYellow\": \"#fffed5\",\n    \"brightBlue\": \"#f92883\",\n    \"brightMagenta\": \"#ffb2fe\",\n    \"brightCyan\": \"#e6e7fe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#030d18\",\n    \"foreground\": \"#f106e3\",\n    \"cursor\": \"#00ff9c\",\n    \"selection\": \"#2e206a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ReagentX\",\n          \"link\": \"https://github.com/ReagentX\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Later This Evening\",\n    \"black\": \"#2b2b2b\",\n    \"red\": \"#d45a60\",\n    \"green\": \"#afba67\",\n    \"yellow\": \"#e5d289\",\n    \"blue\": \"#a0bad6\",\n    \"magenta\": \"#c092d6\",\n    \"cyan\": \"#91bfb7\",\n    \"white\": \"#3c3d3d\",\n    \"brightBlack\": \"#454747\",\n    \"brightRed\": \"#d3232f\",\n    \"brightGreen\": \"#aabb39\",\n    \"brightYellow\": \"#e5be39\",\n    \"brightBlue\": \"#6699d6\",\n    \"brightMagenta\": \"#ab53d6\",\n    \"brightCyan\": \"#5fc0ae\",\n    \"brightWhite\": \"#c1c2c2\",\n    \"background\": \"#222222\",\n    \"foreground\": \"#959595\",\n    \"cursor\": \"#424242\",\n    \"selection\": \"#424242\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vilhalmer\",\n          \"link\": \"https://github.com/vilhalmer/System/tree/master/terminal-themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Lavandula\",\n    \"black\": \"#230046\",\n    \"red\": \"#7d1625\",\n    \"green\": \"#337e6f\",\n    \"yellow\": \"#7f6f49\",\n    \"blue\": \"#4f4a7f\",\n    \"magenta\": \"#5a3f7f\",\n    \"cyan\": \"#58777f\",\n    \"white\": \"#736e7d\",\n    \"brightBlack\": \"#372d46\",\n    \"brightRed\": \"#e05167\",\n    \"brightGreen\": \"#52e0c4\",\n    \"brightYellow\": \"#e0c386\",\n    \"brightBlue\": \"#8e87e0\",\n    \"brightMagenta\": \"#a776e0\",\n    \"brightCyan\": \"#9ad4e0\",\n    \"brightWhite\": \"#8c91fa\",\n    \"background\": \"#050014\",\n    \"foreground\": \"#736e7d\",\n    \"cursor\": \"#8c91fa\",\n    \"selection\": \"#37323c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"LiquidCarbon\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff3030\",\n    \"green\": \"#559a70\",\n    \"yellow\": \"#ccac00\",\n    \"blue\": \"#0099cc\",\n    \"magenta\": \"#cc69c8\",\n    \"cyan\": \"#7ac4cc\",\n    \"white\": \"#bccccc\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#ff3030\",\n    \"brightGreen\": \"#559a70\",\n    \"brightYellow\": \"#ccac00\",\n    \"brightBlue\": \"#0099cc\",\n    \"brightMagenta\": \"#cc69c8\",\n    \"brightCyan\": \"#7ac4cc\",\n    \"brightWhite\": \"#bccccc\",\n    \"background\": \"#303030\",\n    \"foreground\": \"#afc2c2\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#7dbeff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"markcho\",\n          \"link\": \"https://github.com/markcho/iTerm2_LiquidCarbon\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"LiquidCarbonTransparent\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff3030\",\n    \"green\": \"#559a70\",\n    \"yellow\": \"#ccac00\",\n    \"blue\": \"#0099cc\",\n    \"magenta\": \"#cc69c8\",\n    \"cyan\": \"#7ac4cc\",\n    \"white\": \"#bccccc\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#ff3030\",\n    \"brightGreen\": \"#559a70\",\n    \"brightYellow\": \"#ccac00\",\n    \"brightBlue\": \"#0099cc\",\n    \"brightMagenta\": \"#cc69c8\",\n    \"brightCyan\": \"#7ac4cc\",\n    \"brightWhite\": \"#bccccc\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#afc2c2\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#7dbeff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"markcho\",\n          \"link\": \"https://github.com/markcho/iTerm2_LiquidCarbon\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"LiquidCarbonTransparentInverse\",\n    \"black\": \"#bccccd\",\n    \"red\": \"#ff3030\",\n    \"green\": \"#559a70\",\n    \"yellow\": \"#ccac00\",\n    \"blue\": \"#0099cc\",\n    \"magenta\": \"#cc69c8\",\n    \"cyan\": \"#7ac4cc\",\n    \"white\": \"#000000\",\n    \"brightBlack\": \"#ffffff\",\n    \"brightRed\": \"#ff3030\",\n    \"brightGreen\": \"#559a70\",\n    \"brightYellow\": \"#ccac00\",\n    \"brightBlue\": \"#0099cc\",\n    \"brightMagenta\": \"#cc69c8\",\n    \"brightCyan\": \"#7ac4cc\",\n    \"brightWhite\": \"#000000\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#afc2c2\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#7dbeff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"markcho\",\n          \"link\": \"https://github.com/markcho/iTerm2_LiquidCarbon\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"lovelace\",\n    \"black\": \"#282a36\",\n    \"red\": \"#f37f97\",\n    \"green\": \"#5adecd\",\n    \"yellow\": \"#f2a272\",\n    \"blue\": \"#8897f4\",\n    \"magenta\": \"#c574dd\",\n    \"cyan\": \"#79e6f3\",\n    \"white\": \"#fdfdfd\",\n    \"brightBlack\": \"#414458\",\n    \"brightRed\": \"#ff4971\",\n    \"brightGreen\": \"#18e3c8\",\n    \"brightYellow\": \"#ff8037\",\n    \"brightBlue\": \"#556fff\",\n    \"brightMagenta\": \"#b043d1\",\n    \"brightCyan\": \"#3fdcee\",\n    \"brightWhite\": \"#bebec1\",\n    \"background\": \"#1d1f28\",\n    \"foreground\": \"#fdfdfd\",\n    \"cursor\": \"#c574dd\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"nalanbar\",\n          \"link\": \"https://github.com/nalanbar\"\n        },\n        {\n          \"name\": \"elenapan\",\n          \"link\": \"https://github.com/elenapan\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Man Page\",\n    \"black\": \"#000000\",\n    \"red\": \"#cc0000\",\n    \"green\": \"#00a600\",\n    \"yellow\": \"#999900\",\n    \"blue\": \"#0000b2\",\n    \"magenta\": \"#b200b2\",\n    \"cyan\": \"#00a6b2\",\n    \"white\": \"#cccccc\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#e50000\",\n    \"brightGreen\": \"#00d900\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#00e5e5\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#fef49c\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#7f7f7f\",\n    \"selection\": \"#a4c9cd\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Mariana\",\n    \"black\": \"#000000\",\n    \"red\": \"#ec5f66\",\n    \"green\": \"#99c794\",\n    \"yellow\": \"#f9ae58\",\n    \"blue\": \"#6699cc\",\n    \"magenta\": \"#c695c6\",\n    \"cyan\": \"#5fb4b4\",\n    \"white\": \"#f7f7f7\",\n    \"brightBlack\": \"#333333\",\n    \"brightRed\": \"#f97b58\",\n    \"brightGreen\": \"#acd1a8\",\n    \"brightYellow\": \"#fac761\",\n    \"brightBlue\": \"#85add6\",\n    \"brightMagenta\": \"#d8b6d8\",\n    \"brightCyan\": \"#82c4c4\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#343d46\",\n    \"foreground\": \"#d8dee9\",\n    \"cursor\": \"#fcbb6a\",\n    \"selection\": \"#4e5a65\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Material\",\n    \"black\": \"#212121\",\n    \"red\": \"#b7141f\",\n    \"green\": \"#457b24\",\n    \"yellow\": \"#f6981e\",\n    \"blue\": \"#134eb2\",\n    \"magenta\": \"#560088\",\n    \"cyan\": \"#0e717c\",\n    \"white\": \"#efefef\",\n    \"brightBlack\": \"#424242\",\n    \"brightRed\": \"#e83b3f\",\n    \"brightGreen\": \"#7aba3a\",\n    \"brightYellow\": \"#ffea2e\",\n    \"brightBlue\": \"#54a4f3\",\n    \"brightMagenta\": \"#aa4dbc\",\n    \"brightCyan\": \"#26bbd1\",\n    \"brightWhite\": \"#d9d9d9\",\n    \"background\": \"#eaeaea\",\n    \"foreground\": \"#232322\",\n    \"cursor\": \"#16afca\",\n    \"selection\": \"#c2c2c2\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"stoeffel\",\n          \"link\": \"https://github.com/stoeffel/material-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"MaterialDark\",\n    \"black\": \"#212121\",\n    \"red\": \"#b7141f\",\n    \"green\": \"#457b24\",\n    \"yellow\": \"#f6981e\",\n    \"blue\": \"#134eb2\",\n    \"magenta\": \"#560088\",\n    \"cyan\": \"#0e717c\",\n    \"white\": \"#efefef\",\n    \"brightBlack\": \"#424242\",\n    \"brightRed\": \"#e83b3f\",\n    \"brightGreen\": \"#7aba3a\",\n    \"brightYellow\": \"#ffea2e\",\n    \"brightBlue\": \"#54a4f3\",\n    \"brightMagenta\": \"#aa4dbc\",\n    \"brightCyan\": \"#26bbd1\",\n    \"brightWhite\": \"#d9d9d9\",\n    \"background\": \"#232322\",\n    \"foreground\": \"#e5e5e5\",\n    \"cursor\": \"#16afca\",\n    \"selection\": \"#dfdfdf\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"stoeffel\",\n          \"link\": \"https://github.com/stoeffel/material-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"MaterialDarker\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff5370\",\n    \"green\": \"#c3e88d\",\n    \"yellow\": \"#ffcb6b\",\n    \"blue\": \"#82aaff\",\n    \"magenta\": \"#c792ea\",\n    \"cyan\": \"#89ddff\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#545454\",\n    \"brightRed\": \"#ff5370\",\n    \"brightGreen\": \"#c3e88d\",\n    \"brightYellow\": \"#ffcb6b\",\n    \"brightBlue\": \"#82aaff\",\n    \"brightMagenta\": \"#c792ea\",\n    \"brightCyan\": \"#89ddff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#212121\",\n    \"foreground\": \"#eeffff\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#eeffff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jos3s\",\n          \"link\": \"https://github.com/jos3s\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"MaterialDesignColors\",\n    \"black\": \"#435b67\",\n    \"red\": \"#fc3841\",\n    \"green\": \"#5cf19e\",\n    \"yellow\": \"#fed032\",\n    \"blue\": \"#37b6ff\",\n    \"magenta\": \"#fc226e\",\n    \"cyan\": \"#59ffd1\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#a1b0b8\",\n    \"brightRed\": \"#fc746d\",\n    \"brightGreen\": \"#adf7be\",\n    \"brightYellow\": \"#fee16c\",\n    \"brightBlue\": \"#70cfff\",\n    \"brightMagenta\": \"#fc669b\",\n    \"brightCyan\": \"#9affe6\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1d262a\",\n    \"foreground\": \"#e7ebed\",\n    \"cursor\": \"#eaeaea\",\n    \"selection\": \"#4e6a78\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"MaterialOcean\",\n    \"black\": \"#546e7a\",\n    \"red\": \"#ff5370\",\n    \"green\": \"#c3e88d\",\n    \"yellow\": \"#ffcb6b\",\n    \"blue\": \"#82aaff\",\n    \"magenta\": \"#c792ea\",\n    \"cyan\": \"#89ddff\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#546e7a\",\n    \"brightRed\": \"#ff5370\",\n    \"brightGreen\": \"#c3e88d\",\n    \"brightYellow\": \"#ffcb6b\",\n    \"brightBlue\": \"#82aaff\",\n    \"brightMagenta\": \"#c792ea\",\n    \"brightCyan\": \"#89ddff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0f111a\",\n    \"foreground\": \"#8f93a2\",\n    \"cursor\": \"#ffcc00\",\n    \"selection\": \"#1f2233\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"kaicataldo\",\n          \"link\": \"https://github.com/kaicataldo/material.vim/blob/master/terminal-colors/iterm2/material-ocean.itermcolors\"\n        },\n        {\n          \"name\": \"fr3fou\",\n          \"link\": \"https://github.com/fr3fou\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Mathias\",\n    \"black\": \"#000000\",\n    \"red\": \"#e52222\",\n    \"green\": \"#a6e32d\",\n    \"yellow\": \"#fc951e\",\n    \"blue\": \"#c48dff\",\n    \"magenta\": \"#fa2573\",\n    \"cyan\": \"#67d9f0\",\n    \"white\": \"#f2f2f2\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#bbbbbb\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#555555\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"mathiasbynens\",\n          \"link\": \"https://github.com/mathiasbynens/dotfiles\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"matrix\",\n    \"black\": \"#0f191c\",\n    \"red\": \"#23755a\",\n    \"green\": \"#82d967\",\n    \"yellow\": \"#ffd700\",\n    \"blue\": \"#3f5242\",\n    \"magenta\": \"#409931\",\n    \"cyan\": \"#50b45a\",\n    \"white\": \"#507350\",\n    \"brightBlack\": \"#688060\",\n    \"brightRed\": \"#2fc079\",\n    \"brightGreen\": \"#90d762\",\n    \"brightYellow\": \"#faff00\",\n    \"brightBlue\": \"#4f7e7e\",\n    \"brightMagenta\": \"#11ff25\",\n    \"brightCyan\": \"#c1ff8a\",\n    \"brightWhite\": \"#678c61\",\n    \"background\": \"#0f191c\",\n    \"foreground\": \"#426644\",\n    \"cursor\": \"#384545\",\n    \"selection\": \"#18282e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Medallion\",\n    \"black\": \"#000000\",\n    \"red\": \"#b64c00\",\n    \"green\": \"#7c8b16\",\n    \"yellow\": \"#d3bd26\",\n    \"blue\": \"#616bb0\",\n    \"magenta\": \"#8c5a90\",\n    \"cyan\": \"#916c25\",\n    \"white\": \"#cac29a\",\n    \"brightBlack\": \"#5e5219\",\n    \"brightRed\": \"#ff9149\",\n    \"brightGreen\": \"#b2ca3b\",\n    \"brightYellow\": \"#ffe54a\",\n    \"brightBlue\": \"#acb8ff\",\n    \"brightMagenta\": \"#ffa0ff\",\n    \"brightCyan\": \"#ffbc51\",\n    \"brightWhite\": \"#fed698\",\n    \"background\": \"#1d1908\",\n    \"foreground\": \"#cac296\",\n    \"cursor\": \"#d3ba30\",\n    \"selection\": \"#626dac\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"midnight-in-mojave\",\n    \"black\": \"#1e1e1e\",\n    \"red\": \"#ff453a\",\n    \"green\": \"#32d74b\",\n    \"yellow\": \"#ffd60a\",\n    \"blue\": \"#0a84ff\",\n    \"magenta\": \"#bf5af2\",\n    \"cyan\": \"#5ac8fa\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#1e1e1e\",\n    \"brightRed\": \"#ff453a\",\n    \"brightGreen\": \"#32d74b\",\n    \"brightYellow\": \"#ffd60a\",\n    \"brightBlue\": \"#0a84ff\",\n    \"brightMagenta\": \"#bf5af2\",\n    \"brightCyan\": \"#5ac8fa\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1e1e1e\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#32d74b\",\n    \"selection\": \"#4a504d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"OberstKrueger\",\n          \"link\": \"https://github.com/oberstkrueger\"\n        },\n        {\n          \"name\": \"Human Interface Guidelines\",\n          \"link\": \"https://developer.apple.com/design/human-interface-guidelines/macos/overview/themes/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Mirage\",\n    \"black\": \"#011627\",\n    \"red\": \"#ff9999\",\n    \"green\": \"#85cc95\",\n    \"yellow\": \"#ffd700\",\n    \"blue\": \"#7fb5ff\",\n    \"magenta\": \"#ddb3ff\",\n    \"cyan\": \"#21c7a8\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#575656\",\n    \"brightRed\": \"#ff9999\",\n    \"brightGreen\": \"#85cc95\",\n    \"brightYellow\": \"#ffd700\",\n    \"brightBlue\": \"#7fb5ff\",\n    \"brightMagenta\": \"#ddb3ff\",\n    \"brightCyan\": \"#85cc95\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1b2738\",\n    \"foreground\": \"#a6b2c0\",\n    \"cursor\": \"#ddb3ff\",\n    \"selection\": \"#273951\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Tristan Remy\",\n          \"link\": \"https://github.com/tristanremy/mirage\"\n        },\n        {\n          \"name\": \"Gomah\",\n          \"link\": \"https://github.com/Gomah/mirage-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Misterioso\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff4242\",\n    \"green\": \"#74af68\",\n    \"yellow\": \"#ffad29\",\n    \"blue\": \"#338f86\",\n    \"magenta\": \"#9414e6\",\n    \"cyan\": \"#23d7d7\",\n    \"white\": \"#e1e1e0\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff3242\",\n    \"brightGreen\": \"#74cd68\",\n    \"brightYellow\": \"#ffb929\",\n    \"brightBlue\": \"#23d7d7\",\n    \"brightMagenta\": \"#ff37ff\",\n    \"brightCyan\": \"#00ede1\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#2d3743\",\n    \"foreground\": \"#e1e1e0\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#2d37ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"flooose\",\n          \"link\": \"https://github.com/flooose/misterioso-iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Molokai\",\n    \"black\": \"#121212\",\n    \"red\": \"#fa2573\",\n    \"green\": \"#98e123\",\n    \"yellow\": \"#dfd460\",\n    \"blue\": \"#1080d0\",\n    \"magenta\": \"#8700ff\",\n    \"cyan\": \"#43a8d0\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#f6669d\",\n    \"brightGreen\": \"#b1e05f\",\n    \"brightYellow\": \"#fff26d\",\n    \"brightBlue\": \"#00afff\",\n    \"brightMagenta\": \"#af87ff\",\n    \"brightCyan\": \"#51ceff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#121212\",\n    \"foreground\": \"#bbbbbb\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"tomasr\",\n          \"link\": \"https://github.com/tomasr/molokai\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"MonaLisa\",\n    \"black\": \"#351b0e\",\n    \"red\": \"#9b291c\",\n    \"green\": \"#636232\",\n    \"yellow\": \"#c36e28\",\n    \"blue\": \"#515c5d\",\n    \"magenta\": \"#9b1d29\",\n    \"cyan\": \"#588056\",\n    \"white\": \"#f7d75c\",\n    \"brightBlack\": \"#874228\",\n    \"brightRed\": \"#ff4331\",\n    \"brightGreen\": \"#b4b264\",\n    \"brightYellow\": \"#ff9566\",\n    \"brightBlue\": \"#9eb2b4\",\n    \"brightMagenta\": \"#ff5b6a\",\n    \"brightCyan\": \"#8acd8f\",\n    \"brightWhite\": \"#ffe598\",\n    \"background\": \"#120b0d\",\n    \"foreground\": \"#f7d66a\",\n    \"cursor\": \"#c46c32\",\n    \"selection\": \"#f7d66a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Monokai Cmder\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#cccc81\",\n    \"background\": \"#272822\",\n    \"foreground\": \"#cacaca\",\n    \"black\": \"#272822\",\n    \"red\": \"#a70334\",\n    \"green\": \"#74aa04\",\n    \"yellow\": \"#b6b649\",\n    \"blue\": \"#01549e\",\n    \"magenta\": \"#89569c\",\n    \"cyan\": \"#1a83a6\",\n    \"white\": \"#cacaca\",\n    \"brightBlack\": \"#7c7c7c\",\n    \"brightRed\": \"#f3044b\",\n    \"brightGreen\": \"#8dd006\",\n    \"brightYellow\": \"#cccc81\",\n    \"brightBlue\": \"#0383f5\",\n    \"brightMagenta\": \"#a87db8\",\n    \"brightCyan\": \"#58c2e5\",\n    \"brightWhite\": \"#ffffff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vdurante\",\n          \"link\": \"https://github.com/vdurante/windows-terminal-monokai-cmder\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Monokai Pro\",\n    \"background\": \"#403e41\",\n    \"black\": \"#403e41\",\n    \"blue\": \"#fc9867\",\n    \"brightBlack\": \"#727072\",\n    \"brightBlue\": \"#fc9867\",\n    \"brightCyan\": \"#78dce8\",\n    \"brightGreen\": \"#a9dc76\",\n    \"brightMagenta\": \"#ab9df2\",\n    \"brightRed\": \"#ff6188\",\n    \"brightWhite\": \"#fcfcfa\",\n    \"brightYellow\": \"#ffd866\",\n    \"cursor\": \"#fcfcfa\",\n    \"cyan\": \"#78dce8\",\n    \"foreground\": \"#fcfcfa\",\n    \"green\": \"#a9dc76\",\n    \"magenta\": \"#ab9df2\",\n    \"red\": \"#ff6188\",\n    \"selection\": \"#fcfcfa\",\n    \"white\": \"#fcfcfa\",\n    \"yellow\": \"#ffd866\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"monokai\",\n          \"link\": \"https://monokai.pro\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Monokai Pro (Filter Octagon)\",\n    \"black\": \"#000000\",\n    \"red\": \"#d81e00\",\n    \"green\": \"#5ea702\",\n    \"yellow\": \"#cfae00\",\n    \"blue\": \"#427ab3\",\n    \"magenta\": \"#89658e\",\n    \"cyan\": \"#00a7aa\",\n    \"white\": \"#dbded8\",\n    \"brightBlack\": \"#686a66\",\n    \"brightRed\": \"#f54235\",\n    \"brightGreen\": \"#99e343\",\n    \"brightYellow\": \"#fdeb61\",\n    \"brightBlue\": \"#84b0d8\",\n    \"brightMagenta\": \"#bc94b7\",\n    \"brightCyan\": \"#37e6e8\",\n    \"brightWhite\": \"#f1f1f0\",\n    \"background\": \"#282a3a\",\n    \"foreground\": \"#eaf2f1\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"monokai\",\n          \"link\": \"https://monokai.pro\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Monokai Pro (Filter Ristretto)\",\n    \"background\": \"#2C2525\",\n    \"black\": \"#403838\",\n    \"blue\": \"#F38D70\",\n    \"brightBlack\": \"#72696A\",\n    \"brightBlue\": \"#F38D70\",\n    \"brightCyan\": \"#85DACC\",\n    \"brightGreen\": \"#ADDA78\",\n    \"brightMagenta\": \"#A8A9EB\",\n    \"brightRed\": \"#FD6883\",\n    \"brightWhite\": \"#FFF1F3\",\n    \"brightYellow\": \"#F9CC6C\",\n    \"cursor\": \"#FFF1F3\",\n    \"cyan\": \"#85DACC\",\n    \"foreground\": \"#FFF1F3\",\n    \"green\": \"#ADDA78\",\n    \"magenta\": \"#A8A9EB\",\n    \"red\": \"#FD6883\",\n    \"selection\": \"#C3B7B8\",\n    \"white\": \"#FFF1F3\",\n    \"yellow\": \"#F9CC6C\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Monokai Remastered\",\n    \"black\": \"#1a1a1a\",\n    \"red\": \"#f4005f\",\n    \"green\": \"#98e024\",\n    \"yellow\": \"#fd971f\",\n    \"blue\": \"#9d65ff\",\n    \"magenta\": \"#f4005f\",\n    \"cyan\": \"#58d1eb\",\n    \"white\": \"#c4c5b5\",\n    \"brightBlack\": \"#625e4c\",\n    \"brightRed\": \"#f4005f\",\n    \"brightGreen\": \"#98e024\",\n    \"brightYellow\": \"#e0d561\",\n    \"brightBlue\": \"#9d65ff\",\n    \"brightMagenta\": \"#f4005f\",\n    \"brightCyan\": \"#58d1eb\",\n    \"brightWhite\": \"#f6f6ef\",\n    \"background\": \"#0c0c0c\",\n    \"foreground\": \"#d9d9d9\",\n    \"cursor\": \"#fc971f\",\n    \"selection\": \"#343434\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Monokai Soda\",\n    \"black\": \"#1a1a1a\",\n    \"red\": \"#f4005f\",\n    \"green\": \"#98e024\",\n    \"yellow\": \"#fa8419\",\n    \"blue\": \"#9d65ff\",\n    \"magenta\": \"#f4005f\",\n    \"cyan\": \"#58d1eb\",\n    \"white\": \"#c4c5b5\",\n    \"brightBlack\": \"#625e4c\",\n    \"brightRed\": \"#f4005f\",\n    \"brightGreen\": \"#98e024\",\n    \"brightYellow\": \"#e0d561\",\n    \"brightBlue\": \"#9d65ff\",\n    \"brightMagenta\": \"#f4005f\",\n    \"brightCyan\": \"#58d1eb\",\n    \"brightWhite\": \"#f6f6ef\",\n    \"background\": \"#1a1a1a\",\n    \"foreground\": \"#c4c5b5\",\n    \"cursor\": \"#f6f7ec\",\n    \"selection\": \"#343434\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"deepsweet\",\n          \"link\": \"https://github.com/deepsweet/Monokai-Soda-iTerm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Monokai Vivid\",\n    \"black\": \"#121212\",\n    \"red\": \"#fa2934\",\n    \"green\": \"#98e123\",\n    \"yellow\": \"#fff30a\",\n    \"blue\": \"#0443ff\",\n    \"magenta\": \"#f800f8\",\n    \"cyan\": \"#01b6ed\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#838383\",\n    \"brightRed\": \"#f6669d\",\n    \"brightGreen\": \"#b1e05f\",\n    \"brightYellow\": \"#fff26d\",\n    \"brightBlue\": \"#0443ff\",\n    \"brightMagenta\": \"#f200f6\",\n    \"brightCyan\": \"#51ceff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#121212\",\n    \"foreground\": \"#f9f9f9\",\n    \"cursor\": \"#fb0007\",\n    \"selection\": \"#ffffff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vitalymak\",\n          \"link\": \"https://github.com/vitalymak/iTerm2-Color-Schemes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Moonlight II\",\n    \"black\": \"#191a2a\",\n    \"red\": \"#ff757f\",\n    \"green\": \"#c3e88d\",\n    \"yellow\": \"#ffc777\",\n    \"blue\": \"#82aaff\",\n    \"magenta\": \"#c099ff\",\n    \"cyan\": \"#86e1fc\",\n    \"white\": \"#c8d3f5\",\n    \"brightBlack\": \"#828bb8\",\n    \"brightRed\": \"#ff757f\",\n    \"brightGreen\": \"#c3e88d\",\n    \"brightYellow\": \"#ffc777\",\n    \"brightBlue\": \"#82aaff\",\n    \"brightMagenta\": \"#c099ff\",\n    \"brightCyan\": \"#86e1fc\",\n    \"brightWhite\": \"#c8d3f5\",\n    \"background\": \"#222436\",\n    \"foreground\": \"#c8d3f5\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"atomiks\",\n          \"link\": \"https://github.com/atomiks\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"N0tch2k\",\n    \"black\": \"#383838\",\n    \"red\": \"#a95551\",\n    \"green\": \"#666666\",\n    \"yellow\": \"#a98051\",\n    \"blue\": \"#657d3e\",\n    \"magenta\": \"#767676\",\n    \"cyan\": \"#c9c9c9\",\n    \"white\": \"#d0b8a3\",\n    \"brightBlack\": \"#474747\",\n    \"brightRed\": \"#a97775\",\n    \"brightGreen\": \"#8c8c8c\",\n    \"brightYellow\": \"#a99175\",\n    \"brightBlue\": \"#98bd5e\",\n    \"brightMagenta\": \"#a3a3a3\",\n    \"brightCyan\": \"#dcdcdc\",\n    \"brightWhite\": \"#d8c8bb\",\n    \"background\": \"#222222\",\n    \"foreground\": \"#a0a0a0\",\n    \"cursor\": \"#aa9175\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"baskerville\",\n          \"link\": \"https://github.com/baskerville/iTerm-2-Color-Themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"neobones_dark\",\n    \"black\": \"#0f191f\",\n    \"red\": \"#de6e7c\",\n    \"green\": \"#90ff6b\",\n    \"yellow\": \"#b77e64\",\n    \"blue\": \"#8190d4\",\n    \"magenta\": \"#b279a7\",\n    \"cyan\": \"#66a5ad\",\n    \"white\": \"#c6d5cf\",\n    \"brightBlack\": \"#263945\",\n    \"brightRed\": \"#e8838f\",\n    \"brightGreen\": \"#a0ff85\",\n    \"brightYellow\": \"#d68c67\",\n    \"brightBlue\": \"#92a0e2\",\n    \"brightMagenta\": \"#cf86c1\",\n    \"brightCyan\": \"#65b8c1\",\n    \"brightWhite\": \"#98a39e\",\n    \"background\": \"#0f191f\",\n    \"foreground\": \"#c6d5cf\",\n    \"cursor\": \"#ceddd7\",\n    \"selection\": \"#3a3e3d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"neobones_light\",\n    \"black\": \"#e5ede6\",\n    \"red\": \"#a8334c\",\n    \"green\": \"#567a30\",\n    \"yellow\": \"#944927\",\n    \"blue\": \"#286486\",\n    \"magenta\": \"#88507d\",\n    \"cyan\": \"#3b8992\",\n    \"white\": \"#202e18\",\n    \"brightBlack\": \"#b3c6b6\",\n    \"brightRed\": \"#94253e\",\n    \"brightGreen\": \"#3f5a22\",\n    \"brightYellow\": \"#803d1c\",\n    \"brightBlue\": \"#1d5573\",\n    \"brightMagenta\": \"#7b3b70\",\n    \"brightCyan\": \"#2b747c\",\n    \"brightWhite\": \"#415934\",\n    \"background\": \"#e5ede6\",\n    \"foreground\": \"#202e18\",\n    \"cursor\": \"#202e18\",\n    \"selection\": \"#ade48c\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Neon\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff3045\",\n    \"green\": \"#5ffa74\",\n    \"yellow\": \"#fffc7e\",\n    \"blue\": \"#0208cb\",\n    \"magenta\": \"#f924e7\",\n    \"cyan\": \"#00fffc\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff5a5a\",\n    \"brightGreen\": \"#75ff88\",\n    \"brightYellow\": \"#fffd96\",\n    \"brightBlue\": \"#3c40cb\",\n    \"brightMagenta\": \"#f15be5\",\n    \"brightCyan\": \"#88fffe\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#14161a\",\n    \"foreground\": \"#00fffc\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#0013ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Neopolitan\",\n    \"black\": \"#000000\",\n    \"red\": \"#800000\",\n    \"green\": \"#61ce3c\",\n    \"yellow\": \"#fbde2d\",\n    \"blue\": \"#253b76\",\n    \"magenta\": \"#ff0080\",\n    \"cyan\": \"#8da6ce\",\n    \"white\": \"#f8f8f8\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#800000\",\n    \"brightGreen\": \"#61ce3c\",\n    \"brightYellow\": \"#fbde2d\",\n    \"brightBlue\": \"#253b76\",\n    \"brightMagenta\": \"#ff0080\",\n    \"brightCyan\": \"#8da6ce\",\n    \"brightWhite\": \"#f8f8f8\",\n    \"background\": \"#271f19\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#253b76\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"daytonn\",\n          \"link\": \"https://github.com/daytonn/iTerm2-Color-Schemes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Neutron\",\n    \"black\": \"#23252b\",\n    \"red\": \"#b54036\",\n    \"green\": \"#5ab977\",\n    \"yellow\": \"#deb566\",\n    \"blue\": \"#6a7c93\",\n    \"magenta\": \"#a4799d\",\n    \"cyan\": \"#3f94a8\",\n    \"white\": \"#e6e8ef\",\n    \"brightBlack\": \"#23252b\",\n    \"brightRed\": \"#b54036\",\n    \"brightGreen\": \"#5ab977\",\n    \"brightYellow\": \"#deb566\",\n    \"brightBlue\": \"#6a7c93\",\n    \"brightMagenta\": \"#a4799d\",\n    \"brightCyan\": \"#3f94a8\",\n    \"brightWhite\": \"#ebedf2\",\n    \"background\": \"#1c1e22\",\n    \"foreground\": \"#e6e8ef\",\n    \"cursor\": \"#f6f7ec\",\n    \"selection\": \"#2f363e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Ch4s3\",\n          \"link\": \"https://github.com/Ch4s3/iTerm2-Neutron\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Night Owlish Light\",\n    \"black\": \"#011627\",\n    \"red\": \"#d3423e\",\n    \"green\": \"#2aa298\",\n    \"yellow\": \"#daaa01\",\n    \"blue\": \"#4876d6\",\n    \"magenta\": \"#403f53\",\n    \"cyan\": \"#08916a\",\n    \"white\": \"#7a8181\",\n    \"brightBlack\": \"#7a8181\",\n    \"brightRed\": \"#f76e6e\",\n    \"brightGreen\": \"#49d0c5\",\n    \"brightYellow\": \"#dac26b\",\n    \"brightBlue\": \"#5ca7e4\",\n    \"brightMagenta\": \"#697098\",\n    \"brightCyan\": \"#00c990\",\n    \"brightWhite\": \"#989fb1\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#403f53\",\n    \"cursor\": \"#403f53\",\n    \"selection\": \"#f2f2f2\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"praveenpuglia\",\n          \"link\": \"https://github.com/praveenpuglia\"\n        },\n        {\n          \"name\": \"sdras\",\n          \"link\": \"https://github.com/sdras\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"NightLion v1\",\n    \"black\": \"#4c4c4c\",\n    \"red\": \"#bb0000\",\n    \"green\": \"#5fde8f\",\n    \"yellow\": \"#f3f167\",\n    \"blue\": \"#276bd8\",\n    \"magenta\": \"#bb00bb\",\n    \"cyan\": \"#00dadf\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#bbbbbb\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Curvve Media\",\n          \"link\": \"http://www.curvve.com/blog/category/themes/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"NightLion v2\",\n    \"black\": \"#4c4c4c\",\n    \"red\": \"#bb0000\",\n    \"green\": \"#04f623\",\n    \"yellow\": \"#f3f167\",\n    \"blue\": \"#64d0f0\",\n    \"magenta\": \"#ce6fdb\",\n    \"cyan\": \"#00dadf\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#7df71d\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#62cbe8\",\n    \"brightMagenta\": \"#ff9bf5\",\n    \"brightCyan\": \"#00ccd8\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#171717\",\n    \"foreground\": \"#bbbbbb\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Curvve Media\",\n          \"link\": \"http://www.curvve.com/blog/category/themes/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"niji\",\n    \"black\": \"#333333\",\n    \"red\": \"#d23e08\",\n    \"green\": \"#54ca74\",\n    \"yellow\": \"#fff700\",\n    \"blue\": \"#2ab9ff\",\n    \"magenta\": \"#ff50da\",\n    \"cyan\": \"#1ef9f5\",\n    \"white\": \"#ddd0c4\",\n    \"brightBlack\": \"#515151\",\n    \"brightRed\": \"#ffb7b7\",\n    \"brightGreen\": \"#c1ffae\",\n    \"brightYellow\": \"#fcffb8\",\n    \"brightBlue\": \"#8efff3\",\n    \"brightMagenta\": \"#ffa2ed\",\n    \"brightCyan\": \"#bcffc7\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#141515\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#ffc663\",\n    \"selection\": \"#515151\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Nocturnal Winter\",\n    \"black\": \"#4d4d4d\",\n    \"red\": \"#f12d52\",\n    \"green\": \"#09cd7e\",\n    \"yellow\": \"#f5f17a\",\n    \"blue\": \"#3182e0\",\n    \"magenta\": \"#ff2b6d\",\n    \"cyan\": \"#09c87a\",\n    \"white\": \"#fcfcfc\",\n    \"brightBlack\": \"#808080\",\n    \"brightRed\": \"#f16d86\",\n    \"brightGreen\": \"#0ae78d\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6096ff\",\n    \"brightMagenta\": \"#ff78a2\",\n    \"brightCyan\": \"#0ae78d\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0d0d17\",\n    \"foreground\": \"#e6e5e5\",\n    \"cursor\": \"#e6e5e5\",\n    \"selection\": \"#adbdd0\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Shriram Balaji\",\n          \"link\": \"https://github.com/Shriram-Balaji\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"nord\",\n    \"black\": \"#3b4252\",\n    \"red\": \"#bf616a\",\n    \"green\": \"#a3be8c\",\n    \"yellow\": \"#ebcb8b\",\n    \"blue\": \"#81a1c1\",\n    \"magenta\": \"#b48ead\",\n    \"cyan\": \"#88c0d0\",\n    \"white\": \"#e5e9f0\",\n    \"brightBlack\": \"#4c566a\",\n    \"brightRed\": \"#bf616a\",\n    \"brightGreen\": \"#a3be8c\",\n    \"brightYellow\": \"#ebcb8b\",\n    \"brightBlue\": \"#81a1c1\",\n    \"brightMagenta\": \"#b48ead\",\n    \"brightCyan\": \"#8fbcbb\",\n    \"brightWhite\": \"#eceff4\",\n    \"background\": \"#2e3440\",\n    \"foreground\": \"#d8dee9\",\n    \"cursor\": \"#eceff4\",\n    \"selection\": \"#eceff4\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Teraskull\",\n          \"link\": \"https://github.com/Teraskull\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"nord-light\",\n    \"black\": \"#3b4252\",\n    \"red\": \"#bf616a\",\n    \"green\": \"#a3be8c\",\n    \"yellow\": \"#ebcb8b\",\n    \"blue\": \"#81a1c1\",\n    \"magenta\": \"#b48ead\",\n    \"cyan\": \"#88c0d0\",\n    \"white\": \"#d8dee9\",\n    \"brightBlack\": \"#4c566a\",\n    \"brightRed\": \"#bf616a\",\n    \"brightGreen\": \"#a3be8c\",\n    \"brightYellow\": \"#ebcb8b\",\n    \"brightBlue\": \"#81a1c1\",\n    \"brightMagenta\": \"#b48ead\",\n    \"brightCyan\": \"#8fbcbb\",\n    \"brightWhite\": \"#eceff4\",\n    \"background\": \"#e5e9f0\",\n    \"foreground\": \"#414858\",\n    \"cursor\": \"#88c0d0\",\n    \"selection\": \"#d8dee9\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Novel\",\n    \"black\": \"#000000\",\n    \"red\": \"#cc0000\",\n    \"green\": \"#009600\",\n    \"yellow\": \"#d06b00\",\n    \"blue\": \"#0000cc\",\n    \"magenta\": \"#cc00cc\",\n    \"cyan\": \"#0087cc\",\n    \"white\": \"#cccccc\",\n    \"brightBlack\": \"#808080\",\n    \"brightRed\": \"#cc0000\",\n    \"brightGreen\": \"#009600\",\n    \"brightYellow\": \"#d06b00\",\n    \"brightBlue\": \"#0000cc\",\n    \"brightMagenta\": \"#cc00cc\",\n    \"brightCyan\": \"#0087cc\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#dfdbc3\",\n    \"foreground\": \"#3b2322\",\n    \"cursor\": \"#73635a\",\n    \"selection\": \"#a4a390\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Obsidian\",\n    \"black\": \"#000000\",\n    \"red\": \"#a60001\",\n    \"green\": \"#00bb00\",\n    \"yellow\": \"#fecd22\",\n    \"blue\": \"#3a9bdb\",\n    \"magenta\": \"#bb00bb\",\n    \"cyan\": \"#00bbbb\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff0003\",\n    \"brightGreen\": \"#93c863\",\n    \"brightYellow\": \"#fef874\",\n    \"brightBlue\": \"#a1d7ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#283033\",\n    \"foreground\": \"#cdcdcd\",\n    \"cursor\": \"#c0cad0\",\n    \"selection\": \"#3e4c4f\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Ocean\",\n    \"black\": \"#000000\",\n    \"red\": \"#990000\",\n    \"green\": \"#00a600\",\n    \"yellow\": \"#999900\",\n    \"blue\": \"#0000b2\",\n    \"magenta\": \"#b200b2\",\n    \"cyan\": \"#00a6b2\",\n    \"white\": \"#bfbfbf\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#e50000\",\n    \"brightGreen\": \"#00d900\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#00e5e5\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#224fbc\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#7f7f7f\",\n    \"selection\": \"#216dff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Oceanic-Next\",\n    \"black\": \"#121c21\",\n    \"red\": \"#e44754\",\n    \"green\": \"#89bd82\",\n    \"yellow\": \"#f7bd51\",\n    \"blue\": \"#5486c0\",\n    \"magenta\": \"#b77eb8\",\n    \"cyan\": \"#50a5a4\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#52606b\",\n    \"brightRed\": \"#e44754\",\n    \"brightGreen\": \"#89bd82\",\n    \"brightYellow\": \"#f7bd51\",\n    \"brightBlue\": \"#5486c0\",\n    \"brightMagenta\": \"#b77eb8\",\n    \"brightCyan\": \"#50a5a4\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#121b21\",\n    \"foreground\": \"#b3b8c3\",\n    \"cursor\": \"#b3b8c3\",\n    \"selection\": \"#3e4953\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"OceanicMaterial\",\n    \"black\": \"#000000\",\n    \"red\": \"#ee2b2a\",\n    \"green\": \"#40a33f\",\n    \"yellow\": \"#ffea2e\",\n    \"blue\": \"#1e80f0\",\n    \"magenta\": \"#8800a0\",\n    \"cyan\": \"#16afca\",\n    \"white\": \"#a4a4a4\",\n    \"brightBlack\": \"#777777\",\n    \"brightRed\": \"#dc5c60\",\n    \"brightGreen\": \"#70be71\",\n    \"brightYellow\": \"#fff163\",\n    \"brightBlue\": \"#54a4f3\",\n    \"brightMagenta\": \"#aa4dbc\",\n    \"brightCyan\": \"#42c7da\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1c262b\",\n    \"foreground\": \"#c2c8d7\",\n    \"cursor\": \"#b3b8c3\",\n    \"selection\": \"#6dc2b8\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"rahulpatel\",\n          \"link\": \"https://github.com/rahulpatel\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Ollie\",\n    \"black\": \"#000000\",\n    \"red\": \"#ac2e31\",\n    \"green\": \"#31ac61\",\n    \"yellow\": \"#ac4300\",\n    \"blue\": \"#2d57ac\",\n    \"magenta\": \"#b08528\",\n    \"cyan\": \"#1fa6ac\",\n    \"white\": \"#8a8eac\",\n    \"brightBlack\": \"#5b3725\",\n    \"brightRed\": \"#ff3d48\",\n    \"brightGreen\": \"#3bff99\",\n    \"brightYellow\": \"#ff5e1e\",\n    \"brightBlue\": \"#4488ff\",\n    \"brightMagenta\": \"#ffc21d\",\n    \"brightCyan\": \"#1ffaff\",\n    \"brightWhite\": \"#5b6ea7\",\n    \"background\": \"#222125\",\n    \"foreground\": \"#8a8dae\",\n    \"cursor\": \"#5b6ea7\",\n    \"selection\": \"#1e3a66\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"OneDark\",\n    \"black\": \"#1e2127\",\n    \"red\": \"#e06c75\",\n    \"green\": \"#98c379\",\n    \"yellow\": \"#d19a66\",\n    \"blue\": \"#61afef\",\n    \"magenta\": \"#c678dd\",\n    \"cyan\": \"#56b6c2\",\n    \"white\": \"#abb2bf\",\n    \"brightBlack\": \"#5c6370\",\n    \"brightRed\": \"#e06c75\",\n    \"brightGreen\": \"#98c379\",\n    \"brightYellow\": \"#d19a66\",\n    \"brightBlue\": \"#61afef\",\n    \"brightMagenta\": \"#c678dd\",\n    \"brightCyan\": \"#56b6c2\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1e2127\",\n    \"foreground\": \"#abb2bf\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"azrikahar\",\n          \"link\": \"https://github.com/azrikahar\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"OneHalfDark\",\n    \"black\": \"#282c34\",\n    \"red\": \"#e06c75\",\n    \"green\": \"#98c379\",\n    \"yellow\": \"#e5c07b\",\n    \"blue\": \"#61afef\",\n    \"magenta\": \"#c678dd\",\n    \"cyan\": \"#56b6c2\",\n    \"white\": \"#dcdfe4\",\n    \"brightBlack\": \"#282c34\",\n    \"brightRed\": \"#e06c75\",\n    \"brightGreen\": \"#98c379\",\n    \"brightYellow\": \"#e5c07b\",\n    \"brightBlue\": \"#61afef\",\n    \"brightMagenta\": \"#c678dd\",\n    \"brightCyan\": \"#56b6c2\",\n    \"brightWhite\": \"#dcdfe4\",\n    \"background\": \"#282c34\",\n    \"foreground\": \"#dcdfe4\",\n    \"cursor\": \"#a3b3cc\",\n    \"selection\": \"#474e5d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"sonph\",\n          \"link\": \"https://github.com/sonph\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"OneHalfLight\",\n    \"black\": \"#383a42\",\n    \"red\": \"#e45649\",\n    \"green\": \"#50a14f\",\n    \"yellow\": \"#c18401\",\n    \"blue\": \"#0184bc\",\n    \"magenta\": \"#a626a4\",\n    \"cyan\": \"#0997b3\",\n    \"white\": \"#fafafa\",\n    \"brightBlack\": \"#4f525e\",\n    \"brightRed\": \"#e06c75\",\n    \"brightGreen\": \"#98c379\",\n    \"brightYellow\": \"#e5c07b\",\n    \"brightBlue\": \"#61afef\",\n    \"brightMagenta\": \"#c678dd\",\n    \"brightCyan\": \"#56b6c2\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#fafafa\",\n    \"foreground\": \"#383a42\",\n    \"cursor\": \"#bfceff\",\n    \"selection\": \"#bfceff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"sonph\",\n          \"link\": \"https://github.com/sonph\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"OneStar\",\n    \"black\": \"#000000\",\n    \"red\": \"#d13b3b\",\n    \"green\": \"#0dbc79\",\n    \"yellow\": \"#dfdf44\",\n    \"blue\": \"#2472c8\",\n    \"magenta\": \"#c42cc4\",\n    \"cyan\": \"#33a0bb\",\n    \"white\": \"#f1f1f1\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#fa4b4b\",\n    \"brightGreen\": \"#23d18b\",\n    \"brightYellow\": \"#fcfc5c\",\n    \"brightBlue\": \"#3b8eea\",\n    \"brightMagenta\": \"#d861d8\",\n    \"brightCyan\": \"#29b8db\",\n    \"brightWhite\": \"#fafafa\",\n    \"background\": \"#0e0e0e\",\n    \"foreground\": \"#e4e4e4\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jos3s\",\n          \"link\": \"https://github.com/jos3s\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Operator Mono Dark\",\n    \"black\": \"#5a5a5a\",\n    \"red\": \"#ca372d\",\n    \"green\": \"#4d7b3a\",\n    \"yellow\": \"#d4d697\",\n    \"blue\": \"#4387cf\",\n    \"magenta\": \"#b86cb4\",\n    \"cyan\": \"#72d5c6\",\n    \"white\": \"#ced4cd\",\n    \"brightBlack\": \"#9a9b99\",\n    \"brightRed\": \"#c37d62\",\n    \"brightGreen\": \"#83d0a2\",\n    \"brightYellow\": \"#fdfdc5\",\n    \"brightBlue\": \"#89d3f6\",\n    \"brightMagenta\": \"#ff2c7a\",\n    \"brightCyan\": \"#82eada\",\n    \"brightWhite\": \"#fdfdf6\",\n    \"background\": \"#191919\",\n    \"foreground\": \"#c3cac2\",\n    \"cursor\": \"#fcdc08\",\n    \"selection\": \"#19273b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vharadkou\",\n          \"link\": \"https://github.com/vharadkou/OperatorMonoDarkTheme\"\n        },\n        {\n          \"name\": \"dreamyguy\",\n          \"link\": \"https://github.com/dreamyguy/iterm-theme-operator-mono-dark\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Overnight Slumber\",\n    \"black\": \"#0a1222\",\n    \"red\": \"#ffa7c4\",\n    \"green\": \"#85cc95\",\n    \"yellow\": \"#ffcb8b\",\n    \"blue\": \"#8dabe1\",\n    \"magenta\": \"#c792eb\",\n    \"cyan\": \"#78ccf0\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#575656\",\n    \"brightRed\": \"#ffa7c4\",\n    \"brightGreen\": \"#85cc95\",\n    \"brightYellow\": \"#ffcb8b\",\n    \"brightBlue\": \"#8dabe1\",\n    \"brightMagenta\": \"#c792eb\",\n    \"brightCyan\": \"#ffa7c4\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#0e1729\",\n    \"foreground\": \"#ced2d6\",\n    \"cursor\": \"#ffa7c4\",\n    \"selection\": \"#1f2b41\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Cristian Velasquez Ramos\",\n          \"link\": \"https://github.com/cevr/overnight\"\n        },\n        {\n          \"name\": \"Gomah\",\n          \"link\": \"https://github.com/Gomah/overnight-slumber-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"PaleNightHC\",\n    \"black\": \"#000000\",\n    \"red\": \"#f07178\",\n    \"green\": \"#c3e88d\",\n    \"yellow\": \"#ffcb6b\",\n    \"blue\": \"#82aaff\",\n    \"magenta\": \"#c792ea\",\n    \"cyan\": \"#89ddff\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#f6a9ae\",\n    \"brightGreen\": \"#dbf1ba\",\n    \"brightYellow\": \"#ffdfa6\",\n    \"brightBlue\": \"#b4ccff\",\n    \"brightMagenta\": \"#ddbdf2\",\n    \"brightCyan\": \"#b8eaff\",\n    \"brightWhite\": \"#999999\",\n    \"background\": \"#3e4251\",\n    \"foreground\": \"#cccccc\",\n    \"cursor\": \"#ffcb6b\",\n    \"selection\": \"#717cb4\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Mattia Astorino\",\n          \"link\": \"https://github.com/equinusocio\"\n        },\n        {\n          \"name\": \"Kasper\",\n          \"link\": \"https://github.com/Kasper-Liu\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Pandora\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff4242\",\n    \"green\": \"#74af68\",\n    \"yellow\": \"#ffad29\",\n    \"blue\": \"#338f86\",\n    \"magenta\": \"#9414e6\",\n    \"cyan\": \"#23d7d7\",\n    \"white\": \"#e2e2e2\",\n    \"brightBlack\": \"#3f5648\",\n    \"brightRed\": \"#ff3242\",\n    \"brightGreen\": \"#74cd68\",\n    \"brightYellow\": \"#ffb929\",\n    \"brightBlue\": \"#23d7d7\",\n    \"brightMagenta\": \"#ff37ff\",\n    \"brightCyan\": \"#00ede1\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#141e43\",\n    \"foreground\": \"#e1e1e1\",\n    \"cursor\": \"#43d58e\",\n    \"selection\": \"#2d37ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"milosmatic\",\n          \"link\": \"https://github.com/milosmatic/Pandora-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Paraiso Dark\",\n    \"black\": \"#2f1e2e\",\n    \"red\": \"#ef6155\",\n    \"green\": \"#48b685\",\n    \"yellow\": \"#fec418\",\n    \"blue\": \"#06b6ef\",\n    \"magenta\": \"#815ba4\",\n    \"cyan\": \"#5bc4bf\",\n    \"white\": \"#a39e9b\",\n    \"brightBlack\": \"#776e71\",\n    \"brightRed\": \"#ef6155\",\n    \"brightGreen\": \"#48b685\",\n    \"brightYellow\": \"#fec418\",\n    \"brightBlue\": \"#06b6ef\",\n    \"brightMagenta\": \"#815ba4\",\n    \"brightCyan\": \"#5bc4bf\",\n    \"brightWhite\": \"#e7e9db\",\n    \"background\": \"#2f1e2e\",\n    \"foreground\": \"#a39e9b\",\n    \"cursor\": \"#a39e9b\",\n    \"selection\": \"#4f424c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"idleberg\",\n          \"link\": \"https://github.com/idleberg\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"PaulMillr\",\n    \"black\": \"#2a2a2a\",\n    \"red\": \"#ff0000\",\n    \"green\": \"#79ff0f\",\n    \"yellow\": \"#e7bf00\",\n    \"blue\": \"#396bd7\",\n    \"magenta\": \"#b449be\",\n    \"cyan\": \"#66ccff\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#ff0080\",\n    \"brightGreen\": \"#66ff66\",\n    \"brightYellow\": \"#f3d64e\",\n    \"brightBlue\": \"#709aed\",\n    \"brightMagenta\": \"#db67e6\",\n    \"brightCyan\": \"#7adff2\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#f2f2f2\",\n    \"cursor\": \"#4d4d4d\",\n    \"selection\": \"#414141\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"paulmillr\",\n          \"link\": \"https://github.com/paulmillr/dotfiles/tree/master/terminal\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"PencilDark\",\n    \"black\": \"#212121\",\n    \"red\": \"#c30771\",\n    \"green\": \"#10a778\",\n    \"yellow\": \"#a89c14\",\n    \"blue\": \"#008ec4\",\n    \"magenta\": \"#523c79\",\n    \"cyan\": \"#20a5ba\",\n    \"white\": \"#d9d9d9\",\n    \"brightBlack\": \"#424242\",\n    \"brightRed\": \"#fb007a\",\n    \"brightGreen\": \"#5fd7af\",\n    \"brightYellow\": \"#f3e430\",\n    \"brightBlue\": \"#20bbfc\",\n    \"brightMagenta\": \"#6855de\",\n    \"brightCyan\": \"#4fb8cc\",\n    \"brightWhite\": \"#f1f1f1\",\n    \"background\": \"#212121\",\n    \"foreground\": \"#f1f1f1\",\n    \"cursor\": \"#20bbfc\",\n    \"selection\": \"#b6d6fd\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"mattly\",\n          \"link\": \"https://github.com/mattly/iterm-colors-pencil\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"PencilLight\",\n    \"black\": \"#212121\",\n    \"red\": \"#c30771\",\n    \"green\": \"#10a778\",\n    \"yellow\": \"#a89c14\",\n    \"blue\": \"#008ec4\",\n    \"magenta\": \"#523c79\",\n    \"cyan\": \"#20a5ba\",\n    \"white\": \"#d9d9d9\",\n    \"brightBlack\": \"#424242\",\n    \"brightRed\": \"#fb007a\",\n    \"brightGreen\": \"#5fd7af\",\n    \"brightYellow\": \"#f3e430\",\n    \"brightBlue\": \"#20bbfc\",\n    \"brightMagenta\": \"#6855de\",\n    \"brightCyan\": \"#4fb8cc\",\n    \"brightWhite\": \"#f1f1f1\",\n    \"background\": \"#f1f1f1\",\n    \"foreground\": \"#424242\",\n    \"cursor\": \"#20bbfc\",\n    \"selection\": \"#b6d6fd\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"mattly\",\n          \"link\": \"https://github.com/mattly/iterm-colors-pencil\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Peppermint\",\n    \"black\": \"#353535\",\n    \"red\": \"#e74669\",\n    \"green\": \"#89d287\",\n    \"yellow\": \"#dab853\",\n    \"blue\": \"#449fd0\",\n    \"magenta\": \"#da62dc\",\n    \"cyan\": \"#65aaaf\",\n    \"white\": \"#b4b4b4\",\n    \"brightBlack\": \"#535353\",\n    \"brightRed\": \"#e4859b\",\n    \"brightGreen\": \"#a3cca2\",\n    \"brightYellow\": \"#e1e487\",\n    \"brightBlue\": \"#6fbce2\",\n    \"brightMagenta\": \"#e586e7\",\n    \"brightCyan\": \"#96dcdb\",\n    \"brightWhite\": \"#dfdfdf\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#c8c8c8\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#e6e6e6\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Piatto Light\",\n    \"black\": \"#414141\",\n    \"red\": \"#b23771\",\n    \"green\": \"#66781e\",\n    \"yellow\": \"#cd6f34\",\n    \"blue\": \"#3c5ea8\",\n    \"magenta\": \"#a454b2\",\n    \"cyan\": \"#66781e\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#3f3f3f\",\n    \"brightRed\": \"#db3365\",\n    \"brightGreen\": \"#829429\",\n    \"brightYellow\": \"#cd6f34\",\n    \"brightBlue\": \"#3c5ea8\",\n    \"brightMagenta\": \"#a454b2\",\n    \"brightCyan\": \"#829429\",\n    \"brightWhite\": \"#f2f2f2\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#414141\",\n    \"cursor\": \"#5e77c8\",\n    \"selection\": \"#706b4e\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"kovv\",\n          \"link\": \"https://github.com/kovv\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Pnevma\",\n    \"black\": \"#2f2e2d\",\n    \"red\": \"#a36666\",\n    \"green\": \"#90a57d\",\n    \"yellow\": \"#d7af87\",\n    \"blue\": \"#7fa5bd\",\n    \"magenta\": \"#c79ec4\",\n    \"cyan\": \"#8adbb4\",\n    \"white\": \"#d0d0d0\",\n    \"brightBlack\": \"#4a4845\",\n    \"brightRed\": \"#d78787\",\n    \"brightGreen\": \"#afbea2\",\n    \"brightYellow\": \"#e4c9af\",\n    \"brightBlue\": \"#a1bdce\",\n    \"brightMagenta\": \"#d7beda\",\n    \"brightCyan\": \"#b1e7dd\",\n    \"brightWhite\": \"#efefef\",\n    \"background\": \"#1c1c1c\",\n    \"foreground\": \"#d0d0d0\",\n    \"cursor\": \"#e4c9af\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"baskerville\",\n          \"link\": \"https://github.com/baskerville/iTerm-2-Color-Themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Popping and Locking\",\n    \"black\": \"#1d2021\",\n    \"red\": \"#cc241d\",\n    \"green\": \"#98971a\",\n    \"yellow\": \"#d79921\",\n    \"blue\": \"#458588\",\n    \"magenta\": \"#b16286\",\n    \"cyan\": \"#689d6a\",\n    \"white\": \"#a89984\",\n    \"brightBlack\": \"#928374\",\n    \"brightRed\": \"#f42c3e\",\n    \"brightGreen\": \"#b8bb26\",\n    \"brightYellow\": \"#fabd2f\",\n    \"brightBlue\": \"#99c6ca\",\n    \"brightMagenta\": \"#d3869b\",\n    \"brightCyan\": \"#7ec16e\",\n    \"brightWhite\": \"#ebdbb2\",\n    \"background\": \"#181921\",\n    \"foreground\": \"#ebdbb2\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#ebdbb2\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Hedinn Eiriksson\",\n          \"link\": \"https://github.com/hedinne\"\n        },\n        {\n          \"name\": \"didierbroska\",\n          \"link\": \"https://github.com/didierbroska\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"primary\",\n    \"black\": \"#000000\",\n    \"red\": \"#db4437\",\n    \"green\": \"#0f9d58\",\n    \"yellow\": \"#f4b400\",\n    \"blue\": \"#4285f4\",\n    \"magenta\": \"#db4437\",\n    \"cyan\": \"#4285f4\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#db4437\",\n    \"brightGreen\": \"#0f9d58\",\n    \"brightYellow\": \"#f4b400\",\n    \"brightBlue\": \"#4285f4\",\n    \"brightMagenta\": \"#4285f4\",\n    \"brightCyan\": \"#0f9d58\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#656565\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"jayanthkoushik\",\n          \"link\": \"https://github.com/jayanthkoushik\"\n        },\n        {\n          \"name\": \"google\",\n          \"link\": \"https://github.com/google/vim-colorscheme-primary\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Primer\",\n    \"black\": \"#000000\",\n    \"red\": \"#ea4a5a\",\n    \"green\": \"#34d058\",\n    \"yellow\": \"#ffdf5d\",\n    \"blue\": \"#2188ff\",\n    \"magenta\": \"#8a63d2\",\n    \"cyan\": \"#15e2e2\",\n    \"white\": \"#ecf0f1\",\n    \"brightBlack\": \"#4f5861\",\n    \"brightRed\": \"#fdaeb7\",\n    \"brightGreen\": \"#bef5cb\",\n    \"brightYellow\": \"#fff5b1\",\n    \"brightBlue\": \"#c8e1ff\",\n    \"brightMagenta\": \"#d1bcf9\",\n    \"brightCyan\": \"#a2ecec\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1a2b3c\",\n    \"foreground\": \"#ffffff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Pro\",\n    \"black\": \"#000000\",\n    \"red\": \"#990000\",\n    \"green\": \"#00a600\",\n    \"yellow\": \"#999900\",\n    \"blue\": \"#2009db\",\n    \"magenta\": \"#b200b2\",\n    \"cyan\": \"#00a6b2\",\n    \"white\": \"#bfbfbf\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#e50000\",\n    \"brightGreen\": \"#00d900\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#00e5e5\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#f2f2f2\",\n    \"cursor\": \"#4d4d4d\",\n    \"selection\": \"#414141\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Pro Light\",\n    \"black\": \"#000000\",\n    \"red\": \"#e5492b\",\n    \"green\": \"#50d148\",\n    \"yellow\": \"#c6c440\",\n    \"blue\": \"#3b75ff\",\n    \"magenta\": \"#ed66e8\",\n    \"cyan\": \"#4ed2de\",\n    \"white\": \"#dcdcdc\",\n    \"brightBlack\": \"#9f9f9f\",\n    \"brightRed\": \"#ff6640\",\n    \"brightGreen\": \"#61ef57\",\n    \"brightYellow\": \"#f2f156\",\n    \"brightBlue\": \"#0082ff\",\n    \"brightMagenta\": \"#ff7eff\",\n    \"brightCyan\": \"#61f7f8\",\n    \"brightWhite\": \"#f2f2f2\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#191919\",\n    \"cursor\": \"#4d4d4d\",\n    \"selection\": \"#c1ddff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"crowsonkb\",\n          \"link\": \"https://github.com/crowsonkb\"\n        },\n        {\n          \"name\": \"iterm_schemer\",\n          \"link\": \"https://github.com/crowsonkb/iterm_schemer\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Purple Rain\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff260e\",\n    \"green\": \"#9be205\",\n    \"yellow\": \"#ffc400\",\n    \"blue\": \"#00a2fa\",\n    \"magenta\": \"#815bb5\",\n    \"cyan\": \"#00deef\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#565656\",\n    \"brightRed\": \"#ff4250\",\n    \"brightGreen\": \"#b8e36e\",\n    \"brightYellow\": \"#ffd852\",\n    \"brightBlue\": \"#00a6ff\",\n    \"brightMagenta\": \"#ac7bf0\",\n    \"brightCyan\": \"#74fdf3\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#21084a\",\n    \"foreground\": \"#fffbf6\",\n    \"cursor\": \"#ff271d\",\n    \"selection\": \"#287691\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"msorre2\",\n          \"link\": \"https://github.com/msorre2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"purplepeter\",\n    \"black\": \"#0a0520\",\n    \"red\": \"#ff796d\",\n    \"green\": \"#99b481\",\n    \"yellow\": \"#efdfac\",\n    \"blue\": \"#66d9ef\",\n    \"magenta\": \"#e78fcd\",\n    \"cyan\": \"#ba8cff\",\n    \"white\": \"#ffba81\",\n    \"brightBlack\": \"#100b23\",\n    \"brightRed\": \"#f99f92\",\n    \"brightGreen\": \"#b4be8f\",\n    \"brightYellow\": \"#f2e9bf\",\n    \"brightBlue\": \"#79daed\",\n    \"brightMagenta\": \"#ba91d4\",\n    \"brightCyan\": \"#a0a0d6\",\n    \"brightWhite\": \"#b9aed3\",\n    \"background\": \"#2a1a4a\",\n    \"foreground\": \"#ece7fa\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#8689c2\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"DeChamp\",\n          \"link\": \"https://github.com/dechamp\"\n        }\n      ]\n    }\n  },\n  {\n    \"background\": \"#000027\",\n    \"black\": \"#000000\",\n    \"blue\": \"#054663\",\n    \"brightBlack\": \"#626262\",\n    \"brightBlue\": \"#457693\",\n    \"brightCyan\": \"#00586C\",\n    \"brightGreen\": \"#55CE55\",\n    \"brightMagenta\": \"#934593\",\n    \"brightRed\": \"#D8624E\",\n    \"brightWhite\": \"#D8D8D8\",\n    \"brightYellow\": \"#FFA700\",\n    \"cursor\": \"#D8D8D8\",\n    \"cyan\": \"#00485C\",\n    \"foreground\": \"#D8D8D8\",\n    \"green\": \"#157E15\",\n    \"name\": \"QB64 Super Dark Blue\",\n    \"magenta\": \"#631563\",\n    \"red\": \"#98220E\",\n    \"selection\": \"#00586C\",\n    \"white\": \"#989898\",\n    \"yellow\": \"#808000\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jmmv\",\n          \"link\": \"https://github.com/jmmv\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Rapture\",\n    \"black\": \"#000000\",\n    \"red\": \"#fc644d\",\n    \"green\": \"#7afde1\",\n    \"yellow\": \"#fff09b\",\n    \"blue\": \"#6c9bf5\",\n    \"magenta\": \"#ff4fa1\",\n    \"cyan\": \"#64e0ff\",\n    \"white\": \"#c0c9e5\",\n    \"brightBlack\": \"#304b66\",\n    \"brightRed\": \"#fc644d\",\n    \"brightGreen\": \"#7afde1\",\n    \"brightYellow\": \"#fff09b\",\n    \"brightBlue\": \"#6c9bf5\",\n    \"brightMagenta\": \"#ff4fa1\",\n    \"brightCyan\": \"#64e0ff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#111e2a\",\n    \"foreground\": \"#c0c9e5\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#304b66\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Pustur\",\n          \"link\": \"https://github.com/Pustur\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Raycast_Dark\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff5360\",\n    \"green\": \"#59d499\",\n    \"yellow\": \"#ffc531\",\n    \"blue\": \"#56c2ff\",\n    \"magenta\": \"#cf2f98\",\n    \"cyan\": \"#52eee5\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#ff6363\",\n    \"brightGreen\": \"#59d499\",\n    \"brightYellow\": \"#ffc531\",\n    \"brightBlue\": \"#56c2ff\",\n    \"brightMagenta\": \"#cf2f98\",\n    \"brightCyan\": \"#52eee5\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1a1a1a\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#cccccc\",\n    \"selection\": \"#333333\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"thomaspaulmann\",\n          \"link\": \"https://github.com/thomaspaulmann\"\n        },\n        {\n          \"name\": \"itsnwa\",\n          \"link\": \"https://github.com/itsnwa\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Raycast_Light\",\n    \"black\": \"#000000\",\n    \"red\": \"#b12424\",\n    \"green\": \"#006b4f\",\n    \"yellow\": \"#f8a300\",\n    \"blue\": \"#138af2\",\n    \"magenta\": \"#9a1b6e\",\n    \"cyan\": \"#3eb8bf\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#b12424\",\n    \"brightGreen\": \"#006b4f\",\n    \"brightYellow\": \"#f8a300\",\n    \"brightBlue\": \"#138af2\",\n    \"brightMagenta\": \"#9a1b6e\",\n    \"brightCyan\": \"#3eb8bf\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#e5e5e5\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"thomaspaulmann\",\n          \"link\": \"https://github.com/thomaspaulmann\"\n        },\n        {\n          \"name\": \"itsnwa\",\n          \"link\": \"https://github.com/itsnwa\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"rebecca\",\n    \"black\": \"#12131e\",\n    \"red\": \"#dd7755\",\n    \"green\": \"#04dbb5\",\n    \"yellow\": \"#f2e7b7\",\n    \"blue\": \"#7aa5ff\",\n    \"magenta\": \"#bf9cf9\",\n    \"cyan\": \"#56d3c2\",\n    \"white\": \"#e4e3e9\",\n    \"brightBlack\": \"#666699\",\n    \"brightRed\": \"#ff92cd\",\n    \"brightGreen\": \"#01eac0\",\n    \"brightYellow\": \"#fffca8\",\n    \"brightBlue\": \"#69c0fa\",\n    \"brightMagenta\": \"#c17ff8\",\n    \"brightCyan\": \"#8bfde1\",\n    \"brightWhite\": \"#f4f2f9\",\n    \"background\": \"#292a44\",\n    \"foreground\": \"#e8e6ed\",\n    \"cursor\": \"#b89bf9\",\n    \"selection\": \"#663399\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"vic\",\n          \"link\": \"https://github.com/vic\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Red Alert\",\n    \"black\": \"#000000\",\n    \"red\": \"#d62e4e\",\n    \"green\": \"#71be6b\",\n    \"yellow\": \"#beb86b\",\n    \"blue\": \"#489bee\",\n    \"magenta\": \"#e979d7\",\n    \"cyan\": \"#6bbeb8\",\n    \"white\": \"#d6d6d6\",\n    \"brightBlack\": \"#262626\",\n    \"brightRed\": \"#e02553\",\n    \"brightGreen\": \"#aff08c\",\n    \"brightYellow\": \"#dfddb7\",\n    \"brightBlue\": \"#65aaf1\",\n    \"brightMagenta\": \"#ddb7df\",\n    \"brightCyan\": \"#b7dfdd\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#762423\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#073642\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Red Planet\",\n    \"black\": \"#202020\",\n    \"red\": \"#8c3432\",\n    \"green\": \"#728271\",\n    \"yellow\": \"#e8bf6a\",\n    \"blue\": \"#69819e\",\n    \"magenta\": \"#896492\",\n    \"cyan\": \"#5b8390\",\n    \"white\": \"#b9aa99\",\n    \"brightBlack\": \"#676767\",\n    \"brightRed\": \"#b55242\",\n    \"brightGreen\": \"#869985\",\n    \"brightYellow\": \"#ebeb91\",\n    \"brightBlue\": \"#60827e\",\n    \"brightMagenta\": \"#de4974\",\n    \"brightCyan\": \"#38add8\",\n    \"brightWhite\": \"#d6bfb8\",\n    \"background\": \"#222222\",\n    \"foreground\": \"#c2b790\",\n    \"cursor\": \"#c2b790\",\n    \"selection\": \"#1b324a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ibrokemypie\",\n          \"link\": \"https://github.com/ibrokemypie\"\n        },\n        {\n          \"name\": \"eliquious\",\n          \"link\": \"https://github.com/eliquious\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Red Sands\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff3f00\",\n    \"green\": \"#00bb00\",\n    \"yellow\": \"#e7b000\",\n    \"blue\": \"#0072ff\",\n    \"magenta\": \"#bb00bb\",\n    \"cyan\": \"#00bbbb\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#bb0000\",\n    \"brightGreen\": \"#00bb00\",\n    \"brightYellow\": \"#e7b000\",\n    \"brightBlue\": \"#0072ae\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#7a251e\",\n    \"foreground\": \"#d7c9a7\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#a4a390\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Relaxed\",\n    \"black\": \"#151515\",\n    \"red\": \"#bc5653\",\n    \"green\": \"#909d63\",\n    \"yellow\": \"#ebc17a\",\n    \"blue\": \"#6a8799\",\n    \"magenta\": \"#b06698\",\n    \"cyan\": \"#c9dfff\",\n    \"white\": \"#d9d9d9\",\n    \"brightBlack\": \"#636363\",\n    \"brightRed\": \"#bc5653\",\n    \"brightGreen\": \"#a0ac77\",\n    \"brightYellow\": \"#ebc17a\",\n    \"brightBlue\": \"#7eaac7\",\n    \"brightMagenta\": \"#b06698\",\n    \"brightCyan\": \"#acbbd0\",\n    \"brightWhite\": \"#f7f7f7\",\n    \"background\": \"#353a44\",\n    \"foreground\": \"#d9d9d9\",\n    \"cursor\": \"#d9d9d9\",\n    \"selection\": \"#6a7985\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Retro\",\n    \"black\": \"#13a10e\",\n    \"red\": \"#13a10e\",\n    \"green\": \"#13a10e\",\n    \"yellow\": \"#13a10e\",\n    \"blue\": \"#13a10e\",\n    \"magenta\": \"#13a10e\",\n    \"cyan\": \"#13a10e\",\n    \"white\": \"#13a10e\",\n    \"brightBlack\": \"#16ba10\",\n    \"brightRed\": \"#16ba10\",\n    \"brightGreen\": \"#16ba10\",\n    \"brightYellow\": \"#16ba10\",\n    \"brightBlue\": \"#16ba10\",\n    \"brightMagenta\": \"#16ba10\",\n    \"brightCyan\": \"#16ba10\",\n    \"brightWhite\": \"#16ba10\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#13a10e\",\n    \"cursor\": \"#13a10e\",\n    \"selection\": \"#ffffff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Retrowave\",\n    \"background\": \"#070825\",\n    \"foreground\": \"#46BDFF\",\n    \"cyan\": \"#df81fc\",\n    \"brightYellow\": \"#ffffff\",\n    \"brightBlack\": \"#FF16B0\",\n    \"brightGreen\": \"#fcee54\",\n    \"green\": \"#929292\",\n    \"brightRed\": \"#f85353\",\n    \"brightWhite\": \"#ffffff\",\n    \"blue\": \"#46BDFF\",\n    \"brightBlue\": \"#46BDFF\",\n    \"brightCyan\": \"#ff901f\",\n    \"brightMagenta\": \"#FF92DF\",\n    \"magenta\": \"#FF92DF\",\n    \"red\": \"#FF16B0\",\n    \"white\": \"#FFFFFF\",\n    \"black\": \"#181A1F\",\n    \"yellow\": \"#fcee54\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Chrissy LeMaire\",\n          \"link\": \"https://github.com/potatoqualitee\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Rippedcasts\",\n    \"black\": \"#000000\",\n    \"red\": \"#cdaf95\",\n    \"green\": \"#a8ff60\",\n    \"yellow\": \"#bfbb1f\",\n    \"blue\": \"#75a5b0\",\n    \"magenta\": \"#ff73fd\",\n    \"cyan\": \"#5a647e\",\n    \"white\": \"#bfbfbf\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#eecbad\",\n    \"brightGreen\": \"#bcee68\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#86bdc9\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#8c9bc4\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#2b2b2b\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#7f7f7f\",\n    \"selection\": \"#5a647e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"mdw123\",\n          \"link\": \"https://github.com/mdw123/rippedcasts\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Rose Pine\",\n    \"black\": \"#706e86\",\n    \"red\": \"#eb6f92\",\n    \"green\": \"#9ccfd8\",\n    \"yellow\": \"#f6c177\",\n    \"blue\": \"#31748f\",\n    \"magenta\": \"#c4a7e7\",\n    \"cyan\": \"#ebbcba\",\n    \"white\": \"#e0def4\",\n    \"brightBlack\": \"#706e86\",\n    \"brightRed\": \"#eb6f92\",\n    \"brightGreen\": \"#9ccfd8\",\n    \"brightYellow\": \"#f6c177\",\n    \"brightBlue\": \"#31748f\",\n    \"brightMagenta\": \"#c4a7e7\",\n    \"brightCyan\": \"#ebbcba\",\n    \"brightWhite\": \"#e0def4\",\n    \"background\": \"#191724\",\n    \"foreground\": \"#e0def4\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"rose-pine\",\n    \"black\": \"#26233a\",\n    \"red\": \"#eb6f92\",\n    \"green\": \"#9ccfd8\",\n    \"yellow\": \"#f6c177\",\n    \"blue\": \"#31748f\",\n    \"magenta\": \"#c4a7e7\",\n    \"cyan\": \"#ebbcba\",\n    \"white\": \"#e0def4\",\n    \"brightBlack\": \"#6e6a86\",\n    \"brightRed\": \"#eb6f92\",\n    \"brightGreen\": \"#9ccfd8\",\n    \"brightYellow\": \"#f6c177\",\n    \"brightBlue\": \"#31748f\",\n    \"brightMagenta\": \"#c4a7e7\",\n    \"brightCyan\": \"#ebbcba\",\n    \"brightWhite\": \"#e0def4\",\n    \"background\": \"#191724\",\n    \"foreground\": \"#e0def4\",\n    \"cursor\": \"#e0def4\",\n    \"selection\": \"#191724\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"rose-pine-dawn\",\n    \"black\": \"#f2e9e1\",\n    \"red\": \"#b4637a\",\n    \"green\": \"#56949f\",\n    \"yellow\": \"#ea9d34\",\n    \"blue\": \"#286983\",\n    \"magenta\": \"#907aa9\",\n    \"cyan\": \"#d7827e\",\n    \"white\": \"#575279\",\n    \"brightBlack\": \"#9893a5\",\n    \"brightRed\": \"#b4637a\",\n    \"brightGreen\": \"#56949f\",\n    \"brightYellow\": \"#ea9d34\",\n    \"brightBlue\": \"#286983\",\n    \"brightMagenta\": \"#907aa9\",\n    \"brightCyan\": \"#d7827e\",\n    \"brightWhite\": \"#575279\",\n    \"background\": \"#faf4ed\",\n    \"foreground\": \"#575279\",\n    \"cursor\": \"#575279\",\n    \"selection\": \"#faf4ed\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"rose-pine-moon\",\n    \"black\": \"#393552\",\n    \"red\": \"#eb6f92\",\n    \"green\": \"#9ccfd8\",\n    \"yellow\": \"#f6c177\",\n    \"blue\": \"#3e8fb0\",\n    \"magenta\": \"#c4a7e7\",\n    \"cyan\": \"#ea9a97\",\n    \"white\": \"#e0def4\",\n    \"brightBlack\": \"#6e6a86\",\n    \"brightRed\": \"#eb6f92\",\n    \"brightGreen\": \"#9ccfd8\",\n    \"brightYellow\": \"#f6c177\",\n    \"brightBlue\": \"#3e8fb0\",\n    \"brightMagenta\": \"#c4a7e7\",\n    \"brightCyan\": \"#ea9a97\",\n    \"brightWhite\": \"#e0def4\",\n    \"background\": \"#232136\",\n    \"foreground\": \"#e0def4\",\n    \"cursor\": \"#e0def4\",\n    \"selection\": \"#232136\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Rouge 2\",\n    \"black\": \"#5d5d6b\",\n    \"red\": \"#c6797e\",\n    \"green\": \"#969e92\",\n    \"yellow\": \"#dbcdab\",\n    \"blue\": \"#6e94b9\",\n    \"magenta\": \"#4c4e78\",\n    \"cyan\": \"#8ab6c1\",\n    \"white\": \"#e8e8ea\",\n    \"brightBlack\": \"#616274\",\n    \"brightRed\": \"#c6797e\",\n    \"brightGreen\": \"#e6dcc4\",\n    \"brightYellow\": \"#e6dcc4\",\n    \"brightBlue\": \"#98b3cd\",\n    \"brightMagenta\": \"#8283a1\",\n    \"brightCyan\": \"#abcbd3\",\n    \"brightWhite\": \"#e8e8ea\",\n    \"background\": \"#17182b\",\n    \"foreground\": \"#a2a3aa\",\n    \"cursor\": \"#969e92\",\n    \"selection\": \"#5d5d6b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Josef Aidt\",\n          \"link\": \"https://github.com/josefaidt/rouge-theme\"\n        },\n        {\n          \"name\": \"Sam Rose\",\n          \"link\": \"https://github.com/samrose3\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Royal\",\n    \"black\": \"#241f2b\",\n    \"red\": \"#91284c\",\n    \"green\": \"#23801c\",\n    \"yellow\": \"#b49d27\",\n    \"blue\": \"#6580b0\",\n    \"magenta\": \"#674d96\",\n    \"cyan\": \"#8aaabe\",\n    \"white\": \"#524966\",\n    \"brightBlack\": \"#312d3d\",\n    \"brightRed\": \"#d5356c\",\n    \"brightGreen\": \"#2cd946\",\n    \"brightYellow\": \"#fde83b\",\n    \"brightBlue\": \"#90baf9\",\n    \"brightMagenta\": \"#a479e3\",\n    \"brightCyan\": \"#acd4eb\",\n    \"brightWhite\": \"#9e8cbd\",\n    \"background\": \"#100815\",\n    \"foreground\": \"#514968\",\n    \"cursor\": \"#524966\",\n    \"selection\": \"#1f1d2b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Ryuuko\",\n    \"black\": \"#2c3941\",\n    \"red\": \"#865f5b\",\n    \"green\": \"#66907d\",\n    \"yellow\": \"#b1a990\",\n    \"blue\": \"#6a8e95\",\n    \"magenta\": \"#b18a73\",\n    \"cyan\": \"#88b2ac\",\n    \"white\": \"#ececec\",\n    \"brightBlack\": \"#5d7079\",\n    \"brightRed\": \"#865f5b\",\n    \"brightGreen\": \"#66907d\",\n    \"brightYellow\": \"#b1a990\",\n    \"brightBlue\": \"#6a8e95\",\n    \"brightMagenta\": \"#b18a73\",\n    \"brightCyan\": \"#88b2ac\",\n    \"brightWhite\": \"#ececec\",\n    \"background\": \"#2c3941\",\n    \"foreground\": \"#ececec\",\n    \"cursor\": \"#ececec\",\n    \"selection\": \"#002831\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"dylanaraps\",\n          \"link\": \"https://github.com/dylanaraps\"\n        },\n        {\n          \"name\": \"iandrewt\",\n          \"link\": \"https://github.com/iandrewt\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Sakura\",\n    \"black\": \"#000000\",\n    \"red\": \"#d52370\",\n    \"green\": \"#41af1a\",\n    \"yellow\": \"#bc7053\",\n    \"blue\": \"#6964ab\",\n    \"magenta\": \"#c71fbf\",\n    \"cyan\": \"#939393\",\n    \"white\": \"#998eac\",\n    \"brightBlack\": \"#786d69\",\n    \"brightRed\": \"#f41d99\",\n    \"brightGreen\": \"#22e529\",\n    \"brightYellow\": \"#f59574\",\n    \"brightBlue\": \"#9892f1\",\n    \"brightMagenta\": \"#e90cdd\",\n    \"brightCyan\": \"#eeeeee\",\n    \"brightWhite\": \"#cbb6ff\",\n    \"background\": \"#18131e\",\n    \"foreground\": \"#dd7bdc\",\n    \"cursor\": \"#ff65fd\",\n    \"selection\": \"#c05cbf\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"0xN0ri\",\n          \"link\": \"https://github.com/0xN0ri\"\n        },\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Scarlet Protocol\",\n    \"black\": \"#101116\",\n    \"red\": \"#ff0051\",\n    \"green\": \"#00dc84\",\n    \"yellow\": \"#faf945\",\n    \"blue\": \"#0271b6\",\n    \"magenta\": \"#ca30c7\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#ff6e67\",\n    \"brightGreen\": \"#5ffa68\",\n    \"brightYellow\": \"#fffc67\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#bd35ec\",\n    \"brightCyan\": \"#60fdff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1c153d\",\n    \"foreground\": \"#e41951\",\n    \"cursor\": \"#76ff9f\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ReagentX\",\n          \"link\": \"https://github.com/ReagentX\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Seafoam Pastel\",\n    \"black\": \"#757575\",\n    \"red\": \"#825d4d\",\n    \"green\": \"#728c62\",\n    \"yellow\": \"#ada16d\",\n    \"blue\": \"#4d7b82\",\n    \"magenta\": \"#8a7267\",\n    \"cyan\": \"#729494\",\n    \"white\": \"#e0e0e0\",\n    \"brightBlack\": \"#8a8a8a\",\n    \"brightRed\": \"#cf937a\",\n    \"brightGreen\": \"#98d9aa\",\n    \"brightYellow\": \"#fae79d\",\n    \"brightBlue\": \"#7ac3cf\",\n    \"brightMagenta\": \"#d6b2a1\",\n    \"brightCyan\": \"#ade0e0\",\n    \"brightWhite\": \"#e0e0e0\",\n    \"background\": \"#243435\",\n    \"foreground\": \"#d4e7d4\",\n    \"cursor\": \"#57647a\",\n    \"selection\": \"#ffffff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"SeaShells\",\n    \"black\": \"#17384c\",\n    \"red\": \"#d15123\",\n    \"green\": \"#027c9b\",\n    \"yellow\": \"#fca02f\",\n    \"blue\": \"#1e4950\",\n    \"magenta\": \"#68d4f1\",\n    \"cyan\": \"#50a3b5\",\n    \"white\": \"#deb88d\",\n    \"brightBlack\": \"#434b53\",\n    \"brightRed\": \"#d48678\",\n    \"brightGreen\": \"#628d98\",\n    \"brightYellow\": \"#fdd39f\",\n    \"brightBlue\": \"#1bbcdd\",\n    \"brightMagenta\": \"#bbe3ee\",\n    \"brightCyan\": \"#87acb4\",\n    \"brightWhite\": \"#fee4ce\",\n    \"background\": \"#09141b\",\n    \"foreground\": \"#deb88d\",\n    \"cursor\": \"#fca02f\",\n    \"selection\": \"#1e4962\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"seoulbones_dark\",\n    \"black\": \"#4b4b4b\",\n    \"red\": \"#e388a3\",\n    \"green\": \"#98bd99\",\n    \"yellow\": \"#ffdf9b\",\n    \"blue\": \"#97bdde\",\n    \"magenta\": \"#a5a6c5\",\n    \"cyan\": \"#6fbdbe\",\n    \"white\": \"#dddddd\",\n    \"brightBlack\": \"#6c6465\",\n    \"brightRed\": \"#eb99b1\",\n    \"brightGreen\": \"#8fcd92\",\n    \"brightYellow\": \"#ffe5b3\",\n    \"brightBlue\": \"#a2c8e9\",\n    \"brightMagenta\": \"#b2b3da\",\n    \"brightCyan\": \"#6bcacb\",\n    \"brightWhite\": \"#a8a8a8\",\n    \"background\": \"#4b4b4b\",\n    \"foreground\": \"#dddddd\",\n    \"cursor\": \"#e2e2e2\",\n    \"selection\": \"#777777\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"seoulbones_light\",\n    \"black\": \"#e2e2e2\",\n    \"red\": \"#dc5284\",\n    \"green\": \"#628562\",\n    \"yellow\": \"#c48562\",\n    \"blue\": \"#0084a3\",\n    \"magenta\": \"#896788\",\n    \"cyan\": \"#008586\",\n    \"white\": \"#555555\",\n    \"brightBlack\": \"#bfbabb\",\n    \"brightRed\": \"#be3c6d\",\n    \"brightGreen\": \"#487249\",\n    \"brightYellow\": \"#a76b48\",\n    \"brightBlue\": \"#006f89\",\n    \"brightMagenta\": \"#7f4c7e\",\n    \"brightCyan\": \"#006f70\",\n    \"brightWhite\": \"#777777\",\n    \"background\": \"#e2e2e2\",\n    \"foreground\": \"#555555\",\n    \"cursor\": \"#555555\",\n    \"selection\": \"#cccccc\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Serendipity Midnight\",\n    \"background\": \"#1C1E2D\",\n    \"foreground\": \"#DEE0EF\",\n    \"cursor\": \"#6B6D7C\",\n    \"selection\": \"#2C2E3D\",\n    \"black\": \"#232534\",\n    \"brightBlack\": \"#8D8F9E\",\n    \"blue\": \"#5BA2D0\",\n    \"brightBlue\": \"#5BA2D0\",\n    \"cyan\": \"#94B8FF\",\n    \"brightCyan\": \"#94B8FF\",\n    \"magenta\": \"#A78BFA\",\n    \"brightMagenta\": \"#A78BFA\",\n    \"white\": \"#DEE0EF\",\n    \"brightWhite\": \"#DEE0EF\",\n    \"green\": \"#9CCFD8\",\n    \"brightGreen\": \"#9CCFD8\",\n    \"red\": \"#EE8679\",\n    \"brightRed\": \"#EE8679\",\n    \"yellow\": \"#F8D2C9\",\n    \"brightYellow\": \"#F8D2C9\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Michael Andreuzza\",\n          \"link\": \"https://github.com/michael-andreuzza\"\n        },\n        {\n          \"name\": \"Chaphasilor\",\n          \"link\": \"https://github.com/Chaphasilor\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Serendipity Morning\",\n    \"background\": \"#FFFAF3\",\n    \"foreground\": \"#575279\",\n    \"cursor\": \"#9893A5\",\n    \"selection\": \"#F4EFEA\",\n    \"black\": \"#F2E9DE\",\n    \"brightBlack\": \"#6E6A86\",\n    \"blue\": \"#3788BE\",\n    \"brightBlue\": \"#3788BE\",\n    \"cyan\": \"#7397DE\",\n    \"brightCyan\": \"#7397DE\",\n    \"magenta\": \"#886CDB\",\n    \"brightMagenta\": \"#886CDB\",\n    \"white\": \"#575279\",\n    \"brightWhite\": \"#575279\",\n    \"green\": \"#77AAB3\",\n    \"brightGreen\": \"#77AAB3\",\n    \"red\": \"#D26A5D\",\n    \"brightRed\": \"#D26A5D\",\n    \"yellow\": \"#C8A299\",\n    \"brightYellow\": \"#C8A299\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"Michael Andreuzza\",\n          \"link\": \"https://github.com/michael-andreuzza\"\n        },\n        {\n          \"name\": \"Chaphasilor\",\n          \"link\": \"https://github.com/Chaphasilor\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Serendipity Sunset\",\n    \"background\": \"#272938\",\n    \"foreground\": \"#DEE0EF\",\n    \"cursor\": \"#8D8F9E\",\n    \"selection\": \"#313342\",\n    \"black\": \"#363847\",\n    \"brightBlack\": \"#6B6D7C\",\n    \"blue\": \"#709BBD\",\n    \"brightBlue\": \"#709BBD\",\n    \"cyan\": \"#A0B6E8\",\n    \"brightCyan\": \"#A0B6E8\",\n    \"magenta\": \"#A392DC\",\n    \"brightMagenta\": \"#A392DC\",\n    \"white\": \"#DEE0EF\",\n    \"brightWhite\": \"#DEE0EF\",\n    \"green\": \"#AAC9D4\",\n    \"brightGreen\": \"#AAC9D4\",\n    \"red\": \"#D1918F\",\n    \"brightRed\": \"#D1918F\",\n    \"yellow\": \"#EDD5D6\",\n    \"brightYellow\": \"#EDD5D6\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Michael Andreuzza\",\n          \"link\": \"https://github.com/michael-andreuzza\"\n        },\n        {\n          \"name\": \"Chaphasilor\",\n          \"link\": \"https://github.com/Chaphasilor\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Seti\",\n    \"black\": \"#323232\",\n    \"red\": \"#c22832\",\n    \"green\": \"#8ec43d\",\n    \"yellow\": \"#e0c64f\",\n    \"blue\": \"#43a5d5\",\n    \"magenta\": \"#8b57b5\",\n    \"cyan\": \"#8ec43d\",\n    \"white\": \"#eeeeee\",\n    \"brightBlack\": \"#323232\",\n    \"brightRed\": \"#c22832\",\n    \"brightGreen\": \"#8ec43d\",\n    \"brightYellow\": \"#e0c64f\",\n    \"brightBlue\": \"#43a5d5\",\n    \"brightMagenta\": \"#8b57b5\",\n    \"brightCyan\": \"#8ec43d\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#111213\",\n    \"foreground\": \"#cacecd\",\n    \"cursor\": \"#e3bf21\",\n    \"selection\": \"#303233\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"jesseweed\",\n          \"link\": \"https://github.com/jesseweed/seti-syntax/\"\n        },\n        {\n          \"name\": \"philduffy\",\n          \"link\": \"https://github.com/willmanduffy/seti-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"shades-of-purple\",\n    \"black\": \"#000000\",\n    \"red\": \"#d90429\",\n    \"green\": \"#3ad900\",\n    \"yellow\": \"#ffe700\",\n    \"blue\": \"#6943ff\",\n    \"magenta\": \"#ff2c70\",\n    \"cyan\": \"#00c5c7\",\n    \"white\": \"#c7c7c7\",\n    \"brightBlack\": \"#686868\",\n    \"brightRed\": \"#f92a1c\",\n    \"brightGreen\": \"#43d426\",\n    \"brightYellow\": \"#f1d000\",\n    \"brightBlue\": \"#6871ff\",\n    \"brightMagenta\": \"#ff77ff\",\n    \"brightCyan\": \"#79e8fb\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1e1d40\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#fad000\",\n    \"selection\": \"#b362ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ahmadawais\",\n          \"link\": \"https://github.com/ahmadawais/shades-of-purple-iterm2\"\n        },\n        {\n          \"name\": \"fr3fou\",\n          \"link\": \"https://github.com/fr3fou\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Shaman\",\n    \"black\": \"#012026\",\n    \"red\": \"#b2302d\",\n    \"green\": \"#00a941\",\n    \"yellow\": \"#5e8baa\",\n    \"blue\": \"#449a86\",\n    \"magenta\": \"#00599d\",\n    \"cyan\": \"#5d7e19\",\n    \"white\": \"#405555\",\n    \"brightBlack\": \"#384451\",\n    \"brightRed\": \"#ff4242\",\n    \"brightGreen\": \"#2aea5e\",\n    \"brightYellow\": \"#8ed4fd\",\n    \"brightBlue\": \"#61d5ba\",\n    \"brightMagenta\": \"#1298ff\",\n    \"brightCyan\": \"#98d028\",\n    \"brightWhite\": \"#58fbd6\",\n    \"background\": \"#001015\",\n    \"foreground\": \"#405555\",\n    \"cursor\": \"#4afcd6\",\n    \"selection\": \"#415555\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Slate\",\n    \"black\": \"#222222\",\n    \"red\": \"#e2a8bf\",\n    \"green\": \"#81d778\",\n    \"yellow\": \"#c4c9c0\",\n    \"blue\": \"#264b49\",\n    \"magenta\": \"#a481d3\",\n    \"cyan\": \"#15ab9c\",\n    \"white\": \"#02c5e0\",\n    \"brightBlack\": \"#ffffff\",\n    \"brightRed\": \"#ffcdd9\",\n    \"brightGreen\": \"#beffa8\",\n    \"brightYellow\": \"#d0ccca\",\n    \"brightBlue\": \"#7ab0d2\",\n    \"brightMagenta\": \"#c5a7d9\",\n    \"brightCyan\": \"#8cdfe0\",\n    \"brightWhite\": \"#e0e0e0\",\n    \"background\": \"#222222\",\n    \"foreground\": \"#35b1d2\",\n    \"cursor\": \"#87d3c4\",\n    \"selection\": \"#0f3754\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"deneshshan\",\n          \"link\": \"https://github.com/deneshshan\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"SleepyHollow\",\n    \"black\": \"#572100\",\n    \"red\": \"#ba3934\",\n    \"green\": \"#91773f\",\n    \"yellow\": \"#b55600\",\n    \"blue\": \"#5f63b4\",\n    \"magenta\": \"#a17c7b\",\n    \"cyan\": \"#8faea9\",\n    \"white\": \"#af9a91\",\n    \"brightBlack\": \"#4e4b61\",\n    \"brightRed\": \"#d9443f\",\n    \"brightGreen\": \"#d6b04e\",\n    \"brightYellow\": \"#f66813\",\n    \"brightBlue\": \"#8086ef\",\n    \"brightMagenta\": \"#e2c2bb\",\n    \"brightCyan\": \"#a4dce7\",\n    \"brightWhite\": \"#d2c7a9\",\n    \"background\": \"#121214\",\n    \"foreground\": \"#af9a91\",\n    \"cursor\": \"#af9a91\",\n    \"selection\": \"#575256\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Smyck\",\n    \"black\": \"#000000\",\n    \"red\": \"#b84131\",\n    \"green\": \"#7da900\",\n    \"yellow\": \"#c4a500\",\n    \"blue\": \"#62a3c4\",\n    \"magenta\": \"#ba8acc\",\n    \"cyan\": \"#207383\",\n    \"white\": \"#a1a1a1\",\n    \"brightBlack\": \"#7a7a7a\",\n    \"brightRed\": \"#d6837c\",\n    \"brightGreen\": \"#c4f137\",\n    \"brightYellow\": \"#fee14d\",\n    \"brightBlue\": \"#8dcff0\",\n    \"brightMagenta\": \"#f79aff\",\n    \"brightCyan\": \"#6ad9cf\",\n    \"brightWhite\": \"#f7f7f7\",\n    \"background\": \"#1b1b1b\",\n    \"foreground\": \"#f7f7f7\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#207483\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"hukl\",\n          \"link\": \"https://github.com/hukl/Smyck-Color-Scheme\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Snazzy\",\n    \"black\": \"#000000\",\n    \"red\": \"#fc4346\",\n    \"green\": \"#50fb7c\",\n    \"yellow\": \"#f0fb8c\",\n    \"blue\": \"#49baff\",\n    \"magenta\": \"#fc4cb4\",\n    \"cyan\": \"#8be9fe\",\n    \"white\": \"#ededec\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#fc4346\",\n    \"brightGreen\": \"#50fb7c\",\n    \"brightYellow\": \"#f0fb8c\",\n    \"brightBlue\": \"#49baff\",\n    \"brightMagenta\": \"#fc4cb4\",\n    \"brightCyan\": \"#8be9fe\",\n    \"brightWhite\": \"#ededec\",\n    \"background\": \"#1e1f29\",\n    \"foreground\": \"#ebece6\",\n    \"cursor\": \"#e4e4e4\",\n    \"selection\": \"#81aec6\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"SoftServer\",\n    \"black\": \"#000000\",\n    \"red\": \"#a2686a\",\n    \"green\": \"#9aa56a\",\n    \"yellow\": \"#a3906a\",\n    \"blue\": \"#6b8fa3\",\n    \"magenta\": \"#6a71a3\",\n    \"cyan\": \"#6ba58f\",\n    \"white\": \"#99a3a2\",\n    \"brightBlack\": \"#666c6c\",\n    \"brightRed\": \"#dd5c60\",\n    \"brightGreen\": \"#bfdf55\",\n    \"brightYellow\": \"#deb360\",\n    \"brightBlue\": \"#62b1df\",\n    \"brightMagenta\": \"#606edf\",\n    \"brightCyan\": \"#64e39c\",\n    \"brightWhite\": \"#d2e0de\",\n    \"background\": \"#242626\",\n    \"foreground\": \"#99a3a2\",\n    \"cursor\": \"#d2e0de\",\n    \"selection\": \"#7f8786\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Solarized Darcula\",\n    \"black\": \"#25292a\",\n    \"red\": \"#f24840\",\n    \"green\": \"#629655\",\n    \"yellow\": \"#b68800\",\n    \"blue\": \"#2075c7\",\n    \"magenta\": \"#797fd4\",\n    \"cyan\": \"#15968d\",\n    \"white\": \"#d2d8d9\",\n    \"brightBlack\": \"#25292a\",\n    \"brightRed\": \"#f24840\",\n    \"brightGreen\": \"#629655\",\n    \"brightYellow\": \"#b68800\",\n    \"brightBlue\": \"#2075c7\",\n    \"brightMagenta\": \"#797fd4\",\n    \"brightCyan\": \"#15968d\",\n    \"brightWhite\": \"#d2d8d9\",\n    \"background\": \"#3d3f41\",\n    \"foreground\": \"#d2d8d9\",\n    \"cursor\": \"#708284\",\n    \"selection\": \"#214283\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"@rickhanlonii\",\n          \"link\": \"https://github.com/rickhanlonii\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Solarized Dark - Patched\",\n    \"black\": \"#002831\",\n    \"red\": \"#d11c24\",\n    \"green\": \"#738a05\",\n    \"yellow\": \"#a57706\",\n    \"blue\": \"#2176c7\",\n    \"magenta\": \"#c61c6f\",\n    \"cyan\": \"#259286\",\n    \"white\": \"#eae3cb\",\n    \"brightBlack\": \"#475b62\",\n    \"brightRed\": \"#bd3613\",\n    \"brightGreen\": \"#475b62\",\n    \"brightYellow\": \"#536870\",\n    \"brightBlue\": \"#708284\",\n    \"brightMagenta\": \"#5956ba\",\n    \"brightCyan\": \"#819090\",\n    \"brightWhite\": \"#fcf4dc\",\n    \"background\": \"#001e27\",\n    \"foreground\": \"#708284\",\n    \"cursor\": \"#708284\",\n    \"selection\": \"#002831\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Solarized Dark Higher Contrast\",\n    \"black\": \"#002831\",\n    \"red\": \"#d11c24\",\n    \"green\": \"#6cbe6c\",\n    \"yellow\": \"#a57706\",\n    \"blue\": \"#2176c7\",\n    \"magenta\": \"#c61c6f\",\n    \"cyan\": \"#259286\",\n    \"white\": \"#eae3cb\",\n    \"brightBlack\": \"#006488\",\n    \"brightRed\": \"#f5163b\",\n    \"brightGreen\": \"#51ef84\",\n    \"brightYellow\": \"#b27e28\",\n    \"brightBlue\": \"#178ec8\",\n    \"brightMagenta\": \"#e24d8e\",\n    \"brightCyan\": \"#00b39e\",\n    \"brightWhite\": \"#fcf4dc\",\n    \"background\": \"#001e27\",\n    \"foreground\": \"#9cc2c3\",\n    \"cursor\": \"#f34b00\",\n    \"selection\": \"#003748\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"heisters\",\n          \"link\": \"https://gist.github.com/heisters/1015503\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Sonoran Gothic\",\n    \"foreground\": \"#EAF4DE\",\n    \"background\": \"#241F17\",\n    \"cursor\": \"#EAF4DE\",\n    \"black\": \"#867F6E\",\n    \"red\": \"#EB6f6f\",\n    \"green\": \"#669C50\",\n    \"yellow\": \"#F2D696\",\n    \"blue\": \"#227B4d\",\n    \"magenta\": \"#A5ABDA\",\n    \"cyan\": \"#E18F62\",\n    \"white\": \"#EAF4DE\",\n    \"brightBlack\": \"#867F6E\",\n    \"brightRed\": \"#EB6f6f\",\n    \"brightGreen\": \"#669C50\",\n    \"brightYellow\": \"#F2D696\",\n    \"brightBlue\": \"#227B4D\",\n    \"brightMagenta\": \"#A5ABDA\",\n    \"brightCyan\": \"#E18F62\",\n    \"brightWhite\": \"#EAF4DE\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"d-mckee\",\n          \"link\": \"https://github.com/d-mckee\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Sonoran Sunrise\",\n    \"foreground\": \"#61543E\",\n    \"background\": \"#F9FAE3\",\n    \"cursor\": \"#61543E\",\n    \"selection\": \"#a4f017\",\n    \"black\": \"#F9FAE3\",\n    \"red\": \"#EB6f6f\",\n    \"green\": \"#669C50\",\n    \"yellow\": \"#F2C55C\",\n    \"blue\": \"#227B4D\",\n    \"magenta\": \"#7189D9\",\n    \"cyan\": \"#E07941\",\n    \"white\": \"#665E4B\",\n    \"brightBlack\": \"#F9FAE3\",\n    \"brightRed\": \"#EB6f6f\",\n    \"brightGreen\": \"#669C50\",\n    \"brightYellow\": \"#F2C55C\",\n    \"brightBlue\": \"#227B4D\",\n    \"brightMagenta\": \"#7189D9\",\n    \"brightCyan\": \"#E07941\",\n    \"brightWhite\": \"#665E4B\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"d-mckee\",\n          \"link\": \"https://github.com/d-mckee\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Spacedust\",\n    \"black\": \"#6e5346\",\n    \"red\": \"#e35b00\",\n    \"green\": \"#5cab96\",\n    \"yellow\": \"#e3cd7b\",\n    \"blue\": \"#0f548b\",\n    \"magenta\": \"#e35b00\",\n    \"cyan\": \"#06afc7\",\n    \"white\": \"#f0f1ce\",\n    \"brightBlack\": \"#684c31\",\n    \"brightRed\": \"#ff8a3a\",\n    \"brightGreen\": \"#aecab8\",\n    \"brightYellow\": \"#ffc878\",\n    \"brightBlue\": \"#67a0ce\",\n    \"brightMagenta\": \"#ff8a3a\",\n    \"brightCyan\": \"#83a7b4\",\n    \"brightWhite\": \"#fefff1\",\n    \"background\": \"#0a1e24\",\n    \"foreground\": \"#ecf0c1\",\n    \"cursor\": \"#708284\",\n    \"selection\": \"#0a385c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"mhallendal\",\n          \"link\": \"https://github.com/mhallendal/spacedust-theme\"\n        },\n        {\n          \"name\": \"Couto\",\n          \"link\": \"https://github.com/Couto\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"SpaceGray\",\n    \"black\": \"#000000\",\n    \"red\": \"#b04b57\",\n    \"green\": \"#87b379\",\n    \"yellow\": \"#e5c179\",\n    \"blue\": \"#7d8fa4\",\n    \"magenta\": \"#a47996\",\n    \"cyan\": \"#85a7a5\",\n    \"white\": \"#b3b8c3\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#b04b57\",\n    \"brightGreen\": \"#87b379\",\n    \"brightYellow\": \"#e5c179\",\n    \"brightBlue\": \"#7d8fa4\",\n    \"brightMagenta\": \"#a47996\",\n    \"brightCyan\": \"#85a7a5\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#20242d\",\n    \"foreground\": \"#b3b8c3\",\n    \"cursor\": \"#b3b8c3\",\n    \"selection\": \"#16181e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ryentzer\",\n          \"link\": \"https://github.com/ryentzer/SpaceGray-iTerm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"SpaceGray Eighties\",\n    \"black\": \"#15171c\",\n    \"red\": \"#ec5f67\",\n    \"green\": \"#81a764\",\n    \"yellow\": \"#fec254\",\n    \"blue\": \"#5486c0\",\n    \"magenta\": \"#bf83c1\",\n    \"cyan\": \"#57c2c1\",\n    \"white\": \"#efece7\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff6973\",\n    \"brightGreen\": \"#93d493\",\n    \"brightYellow\": \"#ffd256\",\n    \"brightBlue\": \"#4d84d1\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#83e9e4\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#222222\",\n    \"foreground\": \"#bdbaae\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#272e35\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"mhkeller\",\n          \"link\": \"https://github.com/mhkeller/spacegray-eighties-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"SpaceGray Eighties Dull\",\n    \"black\": \"#15171c\",\n    \"red\": \"#b24a56\",\n    \"green\": \"#92b477\",\n    \"yellow\": \"#c6735a\",\n    \"blue\": \"#7c8fa5\",\n    \"magenta\": \"#a5789e\",\n    \"cyan\": \"#80cdcb\",\n    \"white\": \"#b3b8c3\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ec5f67\",\n    \"brightGreen\": \"#89e986\",\n    \"brightYellow\": \"#fec254\",\n    \"brightBlue\": \"#5486c0\",\n    \"brightMagenta\": \"#bf83c1\",\n    \"brightCyan\": \"#58c2c1\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#222222\",\n    \"foreground\": \"#c9c6bc\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#272e36\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"mhkeller\",\n          \"link\": \"https://github.com/mhkeller/spacegray-eighties-iterm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Spiderman\",\n    \"black\": \"#1b1d1e\",\n    \"red\": \"#e60813\",\n    \"green\": \"#e22928\",\n    \"yellow\": \"#e24756\",\n    \"blue\": \"#2c3fff\",\n    \"magenta\": \"#2435db\",\n    \"cyan\": \"#3256ff\",\n    \"white\": \"#fffef6\",\n    \"brightBlack\": \"#505354\",\n    \"brightRed\": \"#ff0325\",\n    \"brightGreen\": \"#ff3338\",\n    \"brightYellow\": \"#fe3a35\",\n    \"brightBlue\": \"#1d50ff\",\n    \"brightMagenta\": \"#747cff\",\n    \"brightCyan\": \"#6184ff\",\n    \"brightWhite\": \"#fffff9\",\n    \"background\": \"#1b1d1e\",\n    \"foreground\": \"#e3e3e3\",\n    \"cursor\": \"#2c3fff\",\n    \"selection\": \"#070e50\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"pyrophos\",\n          \"link\": \"https://github.com/pyrophos\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Spring\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff4d83\",\n    \"green\": \"#1f8c3b\",\n    \"yellow\": \"#1fc95b\",\n    \"blue\": \"#1dd3ee\",\n    \"magenta\": \"#8959a8\",\n    \"cyan\": \"#3e999f\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#ff0021\",\n    \"brightGreen\": \"#1fc231\",\n    \"brightYellow\": \"#d5b807\",\n    \"brightBlue\": \"#15a9fd\",\n    \"brightMagenta\": \"#8959a8\",\n    \"brightCyan\": \"#3e999f\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#4d4d4c\",\n    \"cursor\": \"#4d4d4c\",\n    \"selection\": \"#d6d6d6\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"t3chnoboy\",\n          \"link\": \"https://github.com/t3chnoboy/spring-iTerm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Square\",\n    \"black\": \"#050505\",\n    \"red\": \"#e9897c\",\n    \"green\": \"#b6377d\",\n    \"yellow\": \"#ecebbe\",\n    \"blue\": \"#a9cdeb\",\n    \"magenta\": \"#75507b\",\n    \"cyan\": \"#c9caec\",\n    \"white\": \"#f2f2f2\",\n    \"brightBlack\": \"#141414\",\n    \"brightRed\": \"#f99286\",\n    \"brightGreen\": \"#c3f786\",\n    \"brightYellow\": \"#fcfbcc\",\n    \"brightBlue\": \"#b6defb\",\n    \"brightMagenta\": \"#ad7fa8\",\n    \"brightCyan\": \"#d7d9fc\",\n    \"brightWhite\": \"#e2e2e2\",\n    \"background\": \"#1a1a1a\",\n    \"foreground\": \"#acacab\",\n    \"cursor\": \"#fcfbcc\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"baskerville\",\n          \"link\": \"https://github.com/baskerville/iTerm-2-Color-Themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Sublette\",\n    \"black\": \"#253045\",\n    \"red\": \"#ee5577\",\n    \"green\": \"#55ee77\",\n    \"yellow\": \"#ffdd88\",\n    \"blue\": \"#5588ff\",\n    \"magenta\": \"#ff77cc\",\n    \"cyan\": \"#44eeee\",\n    \"white\": \"#f5f5da\",\n    \"brightBlack\": \"#405570\",\n    \"brightRed\": \"#ee6655\",\n    \"brightGreen\": \"#99ee77\",\n    \"brightYellow\": \"#ffff77\",\n    \"brightBlue\": \"#77bbff\",\n    \"brightMagenta\": \"#aa88ff\",\n    \"brightCyan\": \"#55ffbb\",\n    \"brightWhite\": \"#ffffee\",\n    \"background\": \"#202535\",\n    \"foreground\": \"#ccced0\",\n    \"cursor\": \"#ccced0\",\n    \"selection\": \"#ccced0\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"sublee\",\n          \"link\": \"https://github.com/sublee\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Subliminal\",\n    \"black\": \"#7f7f7f\",\n    \"red\": \"#e15a60\",\n    \"green\": \"#a9cfa4\",\n    \"yellow\": \"#ffe2a9\",\n    \"blue\": \"#6699cc\",\n    \"magenta\": \"#f1a5ab\",\n    \"cyan\": \"#5fb3b3\",\n    \"white\": \"#d4d4d4\",\n    \"brightBlack\": \"#7f7f7f\",\n    \"brightRed\": \"#e15a60\",\n    \"brightGreen\": \"#a9cfa4\",\n    \"brightYellow\": \"#ffe2a9\",\n    \"brightBlue\": \"#6699cc\",\n    \"brightMagenta\": \"#f1a5ab\",\n    \"brightCyan\": \"#5fb3b3\",\n    \"brightWhite\": \"#d4d4d4\",\n    \"background\": \"#282c35\",\n    \"foreground\": \"#d4d4d4\",\n    \"cursor\": \"#c7c7c7\",\n    \"selection\": \"#484e5b\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"gdsrosa\",\n          \"link\": \"https://github.com/gdsrosa/subliminal-itermcolors\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Sundried\",\n    \"black\": \"#302b2a\",\n    \"red\": \"#a7463d\",\n    \"green\": \"#587744\",\n    \"yellow\": \"#9d602a\",\n    \"blue\": \"#485b98\",\n    \"magenta\": \"#864651\",\n    \"cyan\": \"#9c814f\",\n    \"white\": \"#c9c9c9\",\n    \"brightBlack\": \"#4d4e48\",\n    \"brightRed\": \"#aa000c\",\n    \"brightGreen\": \"#128c21\",\n    \"brightYellow\": \"#fc6a21\",\n    \"brightBlue\": \"#7999f7\",\n    \"brightMagenta\": \"#fd8aa1\",\n    \"brightCyan\": \"#fad484\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1a1818\",\n    \"foreground\": \"#c9c9c9\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#302b2a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Symfonic\",\n    \"black\": \"#000000\",\n    \"red\": \"#dc322f\",\n    \"green\": \"#56db3a\",\n    \"yellow\": \"#ff8400\",\n    \"blue\": \"#0084d4\",\n    \"magenta\": \"#b729d9\",\n    \"cyan\": \"#ccccff\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#1b1d21\",\n    \"brightRed\": \"#dc322f\",\n    \"brightGreen\": \"#56db3a\",\n    \"brightYellow\": \"#ff8400\",\n    \"brightBlue\": \"#0084d4\",\n    \"brightMagenta\": \"#b729d9\",\n    \"brightCyan\": \"#ccccff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#dc322f\",\n    \"selection\": \"#073642\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Symfony\",\n          \"link\": \"http://symfony.com/doc/current/book/index.html\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"synthwave\",\n    \"black\": \"#000000\",\n    \"red\": \"#f6188f\",\n    \"green\": \"#1ebb2b\",\n    \"yellow\": \"#fdf834\",\n    \"blue\": \"#2186ec\",\n    \"magenta\": \"#f85a21\",\n    \"cyan\": \"#12c3e2\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#f841a0\",\n    \"brightGreen\": \"#25c141\",\n    \"brightYellow\": \"#fdf454\",\n    \"brightBlue\": \"#2f9ded\",\n    \"brightMagenta\": \"#f97137\",\n    \"brightCyan\": \"#19cde6\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#dad9c7\",\n    \"cursor\": \"#19cde6\",\n    \"selection\": \"#19cde6\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"brettstil\",\n          \"link\": \"https://github.com/brettstil/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"synthwave-everything\",\n    \"black\": \"#fefefe\",\n    \"red\": \"#f97e72\",\n    \"green\": \"#72f1b8\",\n    \"yellow\": \"#fede5d\",\n    \"blue\": \"#6d77b3\",\n    \"magenta\": \"#c792ea\",\n    \"cyan\": \"#f772e0\",\n    \"white\": \"#fefefe\",\n    \"brightBlack\": \"#fefefe\",\n    \"brightRed\": \"#f88414\",\n    \"brightGreen\": \"#72f1b8\",\n    \"brightYellow\": \"#fff951\",\n    \"brightBlue\": \"#36f9f6\",\n    \"brightMagenta\": \"#e1acff\",\n    \"brightCyan\": \"#f92aad\",\n    \"brightWhite\": \"#fefefe\",\n    \"background\": \"#2a2139\",\n    \"foreground\": \"#f0eff1\",\n    \"cursor\": \"#72f1b8\",\n    \"selection\": \"#181521\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"smithbm2316\",\n          \"link\": \"https://github.com/smithbm2316\"\n        },\n        {\n          \"name\": \"robb0wen\",\n          \"link\": \"https://github.com/robb0wen\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"SynthwaveAlpha\",\n    \"black\": \"#241b30\",\n    \"red\": \"#e60a70\",\n    \"green\": \"#00986c\",\n    \"yellow\": \"#adad3e\",\n    \"blue\": \"#6e29ad\",\n    \"magenta\": \"#b300ad\",\n    \"cyan\": \"#00b0b1\",\n    \"white\": \"#b9b1bc\",\n    \"brightBlack\": \"#7f7094\",\n    \"brightRed\": \"#e60a70\",\n    \"brightGreen\": \"#0ae4a4\",\n    \"brightYellow\": \"#f9f972\",\n    \"brightBlue\": \"#aa54f9\",\n    \"brightMagenta\": \"#ff00f6\",\n    \"brightCyan\": \"#00fbfd\",\n    \"brightWhite\": \"#f2f2e3\",\n    \"background\": \"#241b30\",\n    \"foreground\": \"#f2f2e3\",\n    \"cursor\": \"#f2f2e3\",\n    \"selection\": \"#6e29ad\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Tango Adapted\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff0000\",\n    \"green\": \"#59d600\",\n    \"yellow\": \"#f0cb00\",\n    \"blue\": \"#00a2ff\",\n    \"magenta\": \"#c17ecc\",\n    \"cyan\": \"#00d0d6\",\n    \"white\": \"#e6ebe1\",\n    \"brightBlack\": \"#8f928b\",\n    \"brightRed\": \"#ff0013\",\n    \"brightGreen\": \"#93ff00\",\n    \"brightYellow\": \"#fff121\",\n    \"brightBlue\": \"#88c9ff\",\n    \"brightMagenta\": \"#e9a7e1\",\n    \"brightCyan\": \"#00feff\",\n    \"brightWhite\": \"#f6f6f4\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"crowsonkb\",\n          \"link\": \"https://github.com/crowsonkb\"\n        },\n        {\n          \"name\": \"iterm_schemer\",\n          \"link\": \"https://github.com/crowsonkb/iterm_schemer\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Tango Half Adapted\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff0000\",\n    \"green\": \"#4cc300\",\n    \"yellow\": \"#e2c000\",\n    \"blue\": \"#008ef6\",\n    \"magenta\": \"#a96cb3\",\n    \"cyan\": \"#00bdc3\",\n    \"white\": \"#e0e5db\",\n    \"brightBlack\": \"#797d76\",\n    \"brightRed\": \"#ff0013\",\n    \"brightGreen\": \"#8af600\",\n    \"brightYellow\": \"#ffec00\",\n    \"brightBlue\": \"#76bfff\",\n    \"brightMagenta\": \"#d898d1\",\n    \"brightCyan\": \"#00f6fa\",\n    \"brightWhite\": \"#f4f4f2\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#000000\",\n    \"selection\": \"#c1deff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"crowsonkb\",\n          \"link\": \"https://github.com/crowsonkb\"\n        },\n        {\n          \"name\": \"iterm_schemer\",\n          \"link\": \"https://github.com/crowsonkb/iterm_schemer\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Teerb\",\n    \"black\": \"#1c1c1c\",\n    \"red\": \"#d68686\",\n    \"green\": \"#aed686\",\n    \"yellow\": \"#d7af87\",\n    \"blue\": \"#86aed6\",\n    \"magenta\": \"#d6aed6\",\n    \"cyan\": \"#8adbb4\",\n    \"white\": \"#d0d0d0\",\n    \"brightBlack\": \"#1c1c1c\",\n    \"brightRed\": \"#d68686\",\n    \"brightGreen\": \"#aed686\",\n    \"brightYellow\": \"#e4c9af\",\n    \"brightBlue\": \"#86aed6\",\n    \"brightMagenta\": \"#d6aed6\",\n    \"brightCyan\": \"#b1e7dd\",\n    \"brightWhite\": \"#efefef\",\n    \"background\": \"#262626\",\n    \"foreground\": \"#d0d0d0\",\n    \"cursor\": \"#e4c9af\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Teerb\",\n          \"link\": \"https://gist.github.com/teerb/1360453\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Terminal Basic\",\n    \"black\": \"#000000\",\n    \"red\": \"#990000\",\n    \"green\": \"#00a600\",\n    \"yellow\": \"#999900\",\n    \"blue\": \"#0000b2\",\n    \"magenta\": \"#b200b2\",\n    \"cyan\": \"#00a6b2\",\n    \"white\": \"#bfbfbf\",\n    \"brightBlack\": \"#666666\",\n    \"brightRed\": \"#e50000\",\n    \"brightGreen\": \"#00d900\",\n    \"brightYellow\": \"#e5e500\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#e500e5\",\n    \"brightCyan\": \"#00e5e5\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#000000\",\n    \"cursor\": \"#7f7f7f\",\n    \"selection\": \"#a4c9ff\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Thayer Bright\",\n    \"black\": \"#1b1d1e\",\n    \"red\": \"#f92672\",\n    \"green\": \"#4df840\",\n    \"yellow\": \"#f4fd22\",\n    \"blue\": \"#2757d6\",\n    \"magenta\": \"#8c54fe\",\n    \"cyan\": \"#38c8b5\",\n    \"white\": \"#ccccc6\",\n    \"brightBlack\": \"#505354\",\n    \"brightRed\": \"#ff5995\",\n    \"brightGreen\": \"#b6e354\",\n    \"brightYellow\": \"#feed6c\",\n    \"brightBlue\": \"#3f78ff\",\n    \"brightMagenta\": \"#9e6ffe\",\n    \"brightCyan\": \"#23cfd5\",\n    \"brightWhite\": \"#f8f8f2\",\n    \"background\": \"#1b1d1e\",\n    \"foreground\": \"#f8f8f8\",\n    \"cursor\": \"#fc971f\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"t3chnoboy\",\n          \"link\": \"https://github.com/t3chnoboy/thayer-bright-iTerm\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"The Hulk\",\n    \"black\": \"#1b1d1e\",\n    \"red\": \"#269d1b\",\n    \"green\": \"#13ce30\",\n    \"yellow\": \"#63e457\",\n    \"blue\": \"#2525f5\",\n    \"magenta\": \"#641f74\",\n    \"cyan\": \"#378ca9\",\n    \"white\": \"#d9d8d1\",\n    \"brightBlack\": \"#505354\",\n    \"brightRed\": \"#8dff2a\",\n    \"brightGreen\": \"#48ff77\",\n    \"brightYellow\": \"#3afe16\",\n    \"brightBlue\": \"#506b95\",\n    \"brightMagenta\": \"#72589d\",\n    \"brightCyan\": \"#4085a6\",\n    \"brightWhite\": \"#e5e6e1\",\n    \"background\": \"#1b1d1e\",\n    \"foreground\": \"#b5b5b5\",\n    \"cursor\": \"#16b61b\",\n    \"selection\": \"#4d504c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"pyrophos\",\n          \"link\": \"https://github.com/pyrophos\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Tinacious Design (Dark)\",\n    \"black\": \"#1d1d26\",\n    \"red\": \"#ff3399\",\n    \"green\": \"#00d364\",\n    \"yellow\": \"#ffcc66\",\n    \"blue\": \"#00cbff\",\n    \"magenta\": \"#cc66ff\",\n    \"cyan\": \"#00ceca\",\n    \"white\": \"#cbcbf0\",\n    \"brightBlack\": \"#636667\",\n    \"brightRed\": \"#ff2f92\",\n    \"brightGreen\": \"#00d364\",\n    \"brightYellow\": \"#ffd479\",\n    \"brightBlue\": \"#00cbff\",\n    \"brightMagenta\": \"#d783ff\",\n    \"brightCyan\": \"#00d5d4\",\n    \"brightWhite\": \"#d5d6f3\",\n    \"background\": \"#1d1d26\",\n    \"foreground\": \"#cbcbf0\",\n    \"cursor\": \"#cbcbf0\",\n    \"selection\": \"#ff3399\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Tina Holly\",\n          \"link\": \"https://tinaciousdesign.com\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Tinacious Design (Light)\",\n    \"black\": \"#1d1d26\",\n    \"red\": \"#ff3399\",\n    \"green\": \"#00d364\",\n    \"yellow\": \"#ffcc66\",\n    \"blue\": \"#00cbff\",\n    \"magenta\": \"#cc66ff\",\n    \"cyan\": \"#00ceca\",\n    \"white\": \"#cbcbf0\",\n    \"brightBlack\": \"#636667\",\n    \"brightRed\": \"#ff2f92\",\n    \"brightGreen\": \"#00d364\",\n    \"brightYellow\": \"#ffd479\",\n    \"brightBlue\": \"#00cbff\",\n    \"brightMagenta\": \"#d783ff\",\n    \"brightCyan\": \"#00d5d4\",\n    \"brightWhite\": \"#d5d6f3\",\n    \"background\": \"#f8f8ff\",\n    \"foreground\": \"#1d1d26\",\n    \"cursor\": \"#cbcbf0\",\n    \"selection\": \"#ff3399\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"Tina Holly\",\n          \"link\": \"https://tinaciousdesign.com\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"TokyoNight\",\n    \"black\": \"#363b54\",\n    \"red\": \"#f7768e\",\n    \"green\": \"#41a6b5\",\n    \"yellow\": \"#e0af68\",\n    \"blue\": \"#7aa2f7\",\n    \"magenta\": \"#bb9af7\",\n    \"cyan\": \"#7dcfff\",\n    \"white\": \"#787c99\",\n    \"brightBlack\": \"#363b54\",\n    \"brightRed\": \"#f7768e\",\n    \"brightGreen\": \"#41a6b5\",\n    \"brightYellow\": \"#e0af68\",\n    \"brightBlue\": \"#7aa2f7\",\n    \"brightMagenta\": \"#bb9af7\",\n    \"brightCyan\": \"#7dcfff\",\n    \"brightWhite\": \"#acb0d0\",\n    \"background\": \"#16161e\",\n    \"foreground\": \"#787c99\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"tokyonight\",\n    \"black\": \"#15161e\",\n    \"red\": \"#f7768e\",\n    \"green\": \"#9ece6a\",\n    \"yellow\": \"#e0af68\",\n    \"blue\": \"#7aa2f7\",\n    \"magenta\": \"#bb9af7\",\n    \"cyan\": \"#7dcfff\",\n    \"white\": \"#a9b1d6\",\n    \"brightBlack\": \"#414868\",\n    \"brightRed\": \"#f7768e\",\n    \"brightGreen\": \"#9ece6a\",\n    \"brightYellow\": \"#e0af68\",\n    \"brightBlue\": \"#7aa2f7\",\n    \"brightMagenta\": \"#bb9af7\",\n    \"brightCyan\": \"#7dcfff\",\n    \"brightWhite\": \"#c0caf5\",\n    \"background\": \"#1a1b26\",\n    \"foreground\": \"#c0caf5\",\n    \"cursor\": \"#c0caf5\",\n    \"selection\": \"#33467c\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"tokyonight-day\",\n    \"black\": \"#e9e9ed\",\n    \"red\": \"#f52a65\",\n    \"green\": \"#587539\",\n    \"yellow\": \"#8c6c3e\",\n    \"blue\": \"#2e7de9\",\n    \"magenta\": \"#9854f1\",\n    \"cyan\": \"#007197\",\n    \"white\": \"#6172b0\",\n    \"brightBlack\": \"#a1a6c5\",\n    \"brightRed\": \"#f52a65\",\n    \"brightGreen\": \"#587539\",\n    \"brightYellow\": \"#8c6c3e\",\n    \"brightBlue\": \"#2e7de9\",\n    \"brightMagenta\": \"#9854f1\",\n    \"brightCyan\": \"#007197\",\n    \"brightWhite\": \"#3760bf\",\n    \"background\": \"#e1e2e7\",\n    \"foreground\": \"#3760bf\",\n    \"cursor\": \"#3760bf\",\n    \"selection\": \"#99a7df\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"tokyonight-storm\",\n    \"black\": \"#1d202f\",\n    \"red\": \"#f7768e\",\n    \"green\": \"#9ece6a\",\n    \"yellow\": \"#e0af68\",\n    \"blue\": \"#7aa2f7\",\n    \"magenta\": \"#bb9af7\",\n    \"cyan\": \"#7dcfff\",\n    \"white\": \"#a9b1d6\",\n    \"brightBlack\": \"#414868\",\n    \"brightRed\": \"#f7768e\",\n    \"brightGreen\": \"#9ece6a\",\n    \"brightYellow\": \"#e0af68\",\n    \"brightBlue\": \"#7aa2f7\",\n    \"brightMagenta\": \"#bb9af7\",\n    \"brightCyan\": \"#7dcfff\",\n    \"brightWhite\": \"#c0caf5\",\n    \"background\": \"#24283b\",\n    \"foreground\": \"#c0caf5\",\n    \"cursor\": \"#c0caf5\",\n    \"selection\": \"#364a82\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"TokyoNightLight\",\n    \"black\": \"#0f0f14\",\n    \"red\": \"#8c4351\",\n    \"green\": \"#33635c\",\n    \"yellow\": \"#8f5e15\",\n    \"blue\": \"#34548a\",\n    \"magenta\": \"#5a4a78\",\n    \"cyan\": \"#0f4b6e\",\n    \"white\": \"#828594\",\n    \"brightBlack\": \"#0f0f14\",\n    \"brightRed\": \"#8c4351\",\n    \"brightGreen\": \"#33635c\",\n    \"brightYellow\": \"#8f5e15\",\n    \"brightBlue\": \"#34548a\",\n    \"brightMagenta\": \"#5a4a78\",\n    \"brightCyan\": \"#0f4b6e\",\n    \"brightWhite\": \"#828594\",\n    \"background\": \"#cbccd1\",\n    \"foreground\": \"#4c505e\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"TokyoNightStorm\",\n    \"black\": \"#3b4261\",\n    \"red\": \"#f7768e\",\n    \"green\": \"#73daca\",\n    \"yellow\": \"#e0af68\",\n    \"blue\": \"#7aa2f7\",\n    \"magenta\": \"#bb9af7\",\n    \"cyan\": \"#7dcfff\",\n    \"white\": \"#7982a9\",\n    \"brightBlack\": \"#3b4261\",\n    \"brightRed\": \"#f7768e\",\n    \"brightGreen\": \"#73daca\",\n    \"brightYellow\": \"#e0af68\",\n    \"brightBlue\": \"#7aa2f7\",\n    \"brightMagenta\": \"#bb9af7\",\n    \"brightCyan\": \"#7dcfff\",\n    \"brightWhite\": \"#a9b1d6\",\n    \"background\": \"#1f2335\",\n    \"foreground\": \"#7982a9\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Tomorrow\",\n    \"black\": \"#e0e0e0\",\n    \"red\": \"#c82829\",\n    \"green\": \"#718c00\",\n    \"yellow\": \"#eab700\",\n    \"blue\": \"#4271ae\",\n    \"magenta\": \"#8959a8\",\n    \"cyan\": \"#3e999f\",\n    \"white\": \"#282a2e\",\n    \"brightBlack\": \"#d6d6d6\",\n    \"brightRed\": \"#c82829\",\n    \"brightGreen\": \"#718c00\",\n    \"brightYellow\": \"#eab700\",\n    \"brightBlue\": \"#4271ae\",\n    \"brightMagenta\": \"#8959a8\",\n    \"brightCyan\": \"#3e999f\",\n    \"brightWhite\": \"#1d1f21\",\n    \"background\": \"#ffffff\",\n    \"foreground\": \"#4d4d4c\",\n    \"cursor\": \"#4d4d4c\",\n    \"selection\": \"#d6d6d6\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"tinted-theming\",\n          \"link\": \"https://github.com/tinted-theming/base16-schemes/blob/main/tomorrow.yaml\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Tomorrow Night\",\n    \"black\": \"#282a2e\",\n    \"red\": \"#cc6666\",\n    \"green\": \"#b5bd68\",\n    \"yellow\": \"#f0c674\",\n    \"blue\": \"#81a2be\",\n    \"magenta\": \"#b294bb\",\n    \"cyan\": \"#8abeb7\",\n    \"white\": \"#e0e0e0\",\n    \"brightBlack\": \"#373b41\",\n    \"brightRed\": \"#cc6666\",\n    \"brightGreen\": \"#b5bd68\",\n    \"brightYellow\": \"#f0c674\",\n    \"brightBlue\": \"#81a2be\",\n    \"brightMagenta\": \"#b294bb\",\n    \"brightCyan\": \"#8abeb7\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#1d1f21\",\n    \"foreground\": \"#c5c8c6\",\n    \"cursor\": \"#c5c8c6\",\n    \"selection\": \"#373b41\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"tinted-theming\",\n          \"link\": \"https://github.com/tinted-theming/base16-schemes/blob/main/tomorrow-night.yaml\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Tomorrow Night Blue\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff9da4\",\n    \"green\": \"#d1f1a9\",\n    \"yellow\": \"#ffeead\",\n    \"blue\": \"#bbdaff\",\n    \"magenta\": \"#ebbbff\",\n    \"cyan\": \"#99ffff\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#ff9da4\",\n    \"brightGreen\": \"#d1f1a9\",\n    \"brightYellow\": \"#ffeead\",\n    \"brightBlue\": \"#bbdaff\",\n    \"brightMagenta\": \"#ebbbff\",\n    \"brightCyan\": \"#99ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#002451\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#003f8e\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Tomorrow Night Bright\",\n    \"black\": \"#000000\",\n    \"red\": \"#d54e53\",\n    \"green\": \"#b9ca4a\",\n    \"yellow\": \"#e7c547\",\n    \"blue\": \"#7aa6da\",\n    \"magenta\": \"#c397d8\",\n    \"cyan\": \"#70c0b1\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#000000\",\n    \"brightRed\": \"#d54e53\",\n    \"brightGreen\": \"#b9ca4a\",\n    \"brightYellow\": \"#e7c547\",\n    \"brightBlue\": \"#7aa6da\",\n    \"brightMagenta\": \"#c397d8\",\n    \"brightCyan\": \"#70c0b1\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#eaeaea\",\n    \"cursor\": \"#eaeaea\",\n    \"selection\": \"#424242\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Tomorrow Night Burns\",\n    \"black\": \"#252525\",\n    \"red\": \"#832e31\",\n    \"green\": \"#a63c40\",\n    \"yellow\": \"#d3494e\",\n    \"blue\": \"#fc595f\",\n    \"magenta\": \"#df9395\",\n    \"cyan\": \"#ba8586\",\n    \"white\": \"#f5f5f5\",\n    \"brightBlack\": \"#5d6f71\",\n    \"brightRed\": \"#832e31\",\n    \"brightGreen\": \"#a63c40\",\n    \"brightYellow\": \"#d2494e\",\n    \"brightBlue\": \"#fc595f\",\n    \"brightMagenta\": \"#df9395\",\n    \"brightCyan\": \"#ba8586\",\n    \"brightWhite\": \"#f5f5f5\",\n    \"background\": \"#151515\",\n    \"foreground\": \"#a1b0b8\",\n    \"cursor\": \"#ff443e\",\n    \"selection\": \"#b0bec5\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ashwinv11\",\n          \"link\": \"https://github.com/ashwinv11/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Tomorrow Night Eighties\",\n    \"black\": \"#393939\",\n    \"red\": \"#f2777a\",\n    \"green\": \"#99cc99\",\n    \"yellow\": \"#ffcc66\",\n    \"blue\": \"#6699cc\",\n    \"magenta\": \"#cc99cc\",\n    \"cyan\": \"#66cccc\",\n    \"white\": \"#e0e0e0\",\n    \"brightBlack\": \"#515151\",\n    \"brightRed\": \"#f2777a\",\n    \"brightGreen\": \"#99cc99\",\n    \"brightYellow\": \"#ffcc66\",\n    \"brightBlue\": \"#6699cc\",\n    \"brightMagenta\": \"#cc99cc\",\n    \"brightCyan\": \"#66cccc\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#2d2d2d\",\n    \"foreground\": \"#cccccc\",\n    \"cursor\": \"#cccccc\",\n    \"selection\": \"#515151\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": {\n        \"name\": \"tinted-theming\",\n        \"link\": \"https://github.com/tinted-theming/base16-schemes/blob/main/tomorrow-night-eighties.yaml\"\n      }\n    }\n  },\n  {\n    \"name\": \"ToyChest\",\n    \"black\": \"#2c3f58\",\n    \"red\": \"#be2d26\",\n    \"green\": \"#1a9172\",\n    \"yellow\": \"#db8e27\",\n    \"blue\": \"#325d96\",\n    \"magenta\": \"#8a5edc\",\n    \"cyan\": \"#35a08f\",\n    \"white\": \"#23d183\",\n    \"brightBlack\": \"#336889\",\n    \"brightRed\": \"#dd5944\",\n    \"brightGreen\": \"#31d07b\",\n    \"brightYellow\": \"#e7d84b\",\n    \"brightBlue\": \"#34a6da\",\n    \"brightMagenta\": \"#ae6bdc\",\n    \"brightCyan\": \"#42c3ae\",\n    \"brightWhite\": \"#d5d5d5\",\n    \"background\": \"#24364b\",\n    \"foreground\": \"#31d07b\",\n    \"cursor\": \"#d5d5d5\",\n    \"selection\": \"#5f217a\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Treehouse\",\n    \"black\": \"#321300\",\n    \"red\": \"#b2270e\",\n    \"green\": \"#44a900\",\n    \"yellow\": \"#aa820c\",\n    \"blue\": \"#58859a\",\n    \"magenta\": \"#97363d\",\n    \"cyan\": \"#b25a1e\",\n    \"white\": \"#786b53\",\n    \"brightBlack\": \"#433626\",\n    \"brightRed\": \"#ed5d20\",\n    \"brightGreen\": \"#55f238\",\n    \"brightYellow\": \"#f2b732\",\n    \"brightBlue\": \"#85cfed\",\n    \"brightMagenta\": \"#e14c5a\",\n    \"brightCyan\": \"#f07d14\",\n    \"brightWhite\": \"#ffc800\",\n    \"background\": \"#191919\",\n    \"foreground\": \"#786b53\",\n    \"cursor\": \"#fac814\",\n    \"selection\": \"#786b53\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Twilight\",\n    \"black\": \"#141414\",\n    \"red\": \"#c06d44\",\n    \"green\": \"#afb97a\",\n    \"yellow\": \"#c2a86c\",\n    \"blue\": \"#44474a\",\n    \"magenta\": \"#b4be7c\",\n    \"cyan\": \"#778385\",\n    \"white\": \"#ffffd4\",\n    \"brightBlack\": \"#262626\",\n    \"brightRed\": \"#de7c4c\",\n    \"brightGreen\": \"#ccd88c\",\n    \"brightYellow\": \"#e2c47e\",\n    \"brightBlue\": \"#5a5e62\",\n    \"brightMagenta\": \"#d0dc8e\",\n    \"brightCyan\": \"#8a989b\",\n    \"brightWhite\": \"#ffffd4\",\n    \"background\": \"#141414\",\n    \"foreground\": \"#ffffd4\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#313131\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"stefri\",\n          \"link\": \"https://gist.github.com/stefri/1183140\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Ubuntu\",\n    \"black\": \"#2e3436\",\n    \"red\": \"#cc0000\",\n    \"green\": \"#4e9a06\",\n    \"yellow\": \"#c4a000\",\n    \"blue\": \"#3465a4\",\n    \"magenta\": \"#75507b\",\n    \"cyan\": \"#06989a\",\n    \"white\": \"#d3d7cf\",\n    \"brightBlack\": \"#555753\",\n    \"brightRed\": \"#ef2929\",\n    \"brightGreen\": \"#8ae234\",\n    \"brightYellow\": \"#fce94f\",\n    \"brightBlue\": \"#729fcf\",\n    \"brightMagenta\": \"#ad7fa8\",\n    \"brightCyan\": \"#34e2e2\",\n    \"brightWhite\": \"#eeeeec\",\n    \"background\": \"#300a24\",\n    \"foreground\": \"#eeeeec\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Maximus\",\n          \"link\": \"http://superuser.com/questions/497240/ubuntu-purple-terminal-colors-in-conemu\"\n        },\n        {\n          \"name\": \"stepin\",\n          \"link\": \"https://github.com/stepin\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"UltraDark\",\n    \"black\": \"#000000\",\n    \"red\": \"#f07178\",\n    \"green\": \"#c3e88d\",\n    \"yellow\": \"#ffcb6b\",\n    \"blue\": \"#82aaff\",\n    \"magenta\": \"#c792ea\",\n    \"cyan\": \"#89ddff\",\n    \"white\": \"#cccccc\",\n    \"brightBlack\": \"#333333\",\n    \"brightRed\": \"#f6a9ae\",\n    \"brightGreen\": \"#dbf1ba\",\n    \"brightYellow\": \"#ffdfa6\",\n    \"brightBlue\": \"#b4ccff\",\n    \"brightMagenta\": \"#ddbdf2\",\n    \"brightCyan\": \"#b8eaff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#fefefe\",\n    \"selection\": \"#222222\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"UltraViolent\",\n    \"black\": \"#242728\",\n    \"red\": \"#ff0090\",\n    \"green\": \"#b6ff00\",\n    \"yellow\": \"#fff727\",\n    \"blue\": \"#47e0fb\",\n    \"magenta\": \"#d731ff\",\n    \"cyan\": \"#0effbb\",\n    \"white\": \"#e1e1e1\",\n    \"brightBlack\": \"#636667\",\n    \"brightRed\": \"#fb58b4\",\n    \"brightGreen\": \"#deff8c\",\n    \"brightYellow\": \"#ebe087\",\n    \"brightBlue\": \"#7fecff\",\n    \"brightMagenta\": \"#e681ff\",\n    \"brightCyan\": \"#69fcd3\",\n    \"brightWhite\": \"#f9f9f5\",\n    \"background\": \"#242728\",\n    \"foreground\": \"#c1c1c1\",\n    \"cursor\": \"#c1c1c1\",\n    \"selection\": \"#574c49\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"UnderTheSea\",\n    \"black\": \"#022026\",\n    \"red\": \"#b2302d\",\n    \"green\": \"#00a941\",\n    \"yellow\": \"#59819c\",\n    \"blue\": \"#459a86\",\n    \"magenta\": \"#00599d\",\n    \"cyan\": \"#5d7e19\",\n    \"white\": \"#405555\",\n    \"brightBlack\": \"#384451\",\n    \"brightRed\": \"#ff4242\",\n    \"brightGreen\": \"#2aea5e\",\n    \"brightYellow\": \"#8ed4fd\",\n    \"brightBlue\": \"#61d5ba\",\n    \"brightMagenta\": \"#1298ff\",\n    \"brightCyan\": \"#98d028\",\n    \"brightWhite\": \"#58fbd6\",\n    \"background\": \"#011116\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#4afcd6\",\n    \"selection\": \"#415555\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"peterpme\",\n          \"link\": \"https://github.com/peterpme\"\n        }\n      ]\n    }\n  },\n  {\n    \"background\": \"#202020\",\n    \"black\": \"#808080\",\n    \"blue\": \"#65AEF7\",\n    \"brightBlack\": \"#808080\",\n    \"brightBlue\": \"#569CD6\",\n    \"brightCyan\": \"#9CDCFE\",\n    \"brightGreen\": \"#B5CEA8\",\n    \"brightMagenta\": \"#AE81FF\",\n    \"brightRed\": \"#D16969\",\n    \"brightWhite\": \"#FFFFFF\",\n    \"brightYellow\": \"#DCDCAA\",\n    \"cursor\": \"#F8F8F0\",\n    \"cyan\": \"#9CDCFE\",\n    \"foreground\": \"#F8F8F2\",\n    \"green\": \"#608B4E\",\n    \"name\": \"Unholy\",\n    \"magenta\": \"#AE81FF\",\n    \"red\": \"#D16969\",\n    \"selection\": \"#616161\",\n    \"white\": \"#FFFFFF\",\n    \"yellow\": \"#FDD877\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Unikitty\",\n    \"black\": \"#0c0c0c\",\n    \"red\": \"#a80f20\",\n    \"green\": \"#bafc8b\",\n    \"yellow\": \"#eedf4b\",\n    \"blue\": \"#145fcd\",\n    \"magenta\": \"#ff36a2\",\n    \"cyan\": \"#6bd1bc\",\n    \"white\": \"#e2d7e1\",\n    \"brightBlack\": \"#434343\",\n    \"brightRed\": \"#d91329\",\n    \"brightGreen\": \"#d3ffaf\",\n    \"brightYellow\": \"#ffef50\",\n    \"brightBlue\": \"#0075ea\",\n    \"brightMagenta\": \"#fdd5e5\",\n    \"brightCyan\": \"#79ecd5\",\n    \"brightWhite\": \"#fff3fe\",\n    \"background\": \"#ff8cd9\",\n    \"foreground\": \"#0b0b0b\",\n    \"cursor\": \"#bafc8b\",\n    \"selection\": \"#3ea9fe\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"jakebathman\",\n          \"link\": \"https://github.com/jakebathman\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Urple\",\n    \"black\": \"#000000\",\n    \"red\": \"#b0425b\",\n    \"green\": \"#37a415\",\n    \"yellow\": \"#ad5c42\",\n    \"blue\": \"#564d9b\",\n    \"magenta\": \"#6c3ca1\",\n    \"cyan\": \"#808080\",\n    \"white\": \"#87799c\",\n    \"brightBlack\": \"#5d3225\",\n    \"brightRed\": \"#ff6388\",\n    \"brightGreen\": \"#29e620\",\n    \"brightYellow\": \"#f08161\",\n    \"brightBlue\": \"#867aed\",\n    \"brightMagenta\": \"#a05eee\",\n    \"brightCyan\": \"#eaeaea\",\n    \"brightWhite\": \"#bfa3ff\",\n    \"background\": \"#1b1b23\",\n    \"foreground\": \"#877a9b\",\n    \"cursor\": \"#a063eb\",\n    \"selection\": \"#a063eb\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"zdj\",\n          \"link\": \"https://github.com/zdj/themes/tree/master/iterm2\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Vaughn\",\n    \"black\": \"#25234f\",\n    \"red\": \"#705050\",\n    \"green\": \"#60b48a\",\n    \"yellow\": \"#dfaf8f\",\n    \"blue\": \"#5555ff\",\n    \"magenta\": \"#f08cc3\",\n    \"cyan\": \"#8cd0d3\",\n    \"white\": \"#709080\",\n    \"brightBlack\": \"#709080\",\n    \"brightRed\": \"#dca3a3\",\n    \"brightGreen\": \"#60b48a\",\n    \"brightYellow\": \"#f0dfaf\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ec93d3\",\n    \"brightCyan\": \"#93e0e3\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#25234f\",\n    \"foreground\": \"#dcdccc\",\n    \"cursor\": \"#ff5555\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"VibrantInk\",\n    \"black\": \"#878787\",\n    \"red\": \"#ff6600\",\n    \"green\": \"#ccff04\",\n    \"yellow\": \"#ffcc00\",\n    \"blue\": \"#44b4cc\",\n    \"magenta\": \"#9933cc\",\n    \"cyan\": \"#44b4cc\",\n    \"white\": \"#f5f5f5\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff0000\",\n    \"brightGreen\": \"#00ff00\",\n    \"brightYellow\": \"#ffff00\",\n    \"brightBlue\": \"#0000ff\",\n    \"brightMagenta\": \"#ff00ff\",\n    \"brightCyan\": \"#00ffff\",\n    \"brightWhite\": \"#e5e5e5\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#ffffff\",\n    \"cursor\": \"#ffffff\",\n    \"selection\": \"#b5d5ff\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"asanghi\",\n          \"link\": \"https://github.com/asanghi/vibrantinklion\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"vimbones\",\n    \"black\": \"#f0f0ca\",\n    \"red\": \"#a8334c\",\n    \"green\": \"#4f6c31\",\n    \"yellow\": \"#944927\",\n    \"blue\": \"#286486\",\n    \"magenta\": \"#88507d\",\n    \"cyan\": \"#3b8992\",\n    \"white\": \"#353535\",\n    \"brightBlack\": \"#c6c6a3\",\n    \"brightRed\": \"#94253e\",\n    \"brightGreen\": \"#3f5a22\",\n    \"brightYellow\": \"#803d1c\",\n    \"brightBlue\": \"#1d5573\",\n    \"brightMagenta\": \"#7b3b70\",\n    \"brightCyan\": \"#2b747c\",\n    \"brightWhite\": \"#5c5c5c\",\n    \"background\": \"#f0f0ca\",\n    \"foreground\": \"#353535\",\n    \"cursor\": \"#353535\",\n    \"selection\": \"#d7d7d7\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Violet Dark\",\n    \"black\": \"#56595c\",\n    \"red\": \"#c94c22\",\n    \"green\": \"#85981c\",\n    \"yellow\": \"#b4881d\",\n    \"blue\": \"#2e8bce\",\n    \"magenta\": \"#d13a82\",\n    \"cyan\": \"#32a198\",\n    \"white\": \"#c9c6bd\",\n    \"brightBlack\": \"#45484b\",\n    \"brightRed\": \"#bd3613\",\n    \"brightGreen\": \"#738a04\",\n    \"brightYellow\": \"#a57705\",\n    \"brightBlue\": \"#2176c7\",\n    \"brightMagenta\": \"#c61c6f\",\n    \"brightCyan\": \"#259286\",\n    \"brightWhite\": \"#c9c6bd\",\n    \"background\": \"#1c1d1f\",\n    \"foreground\": \"#708284\",\n    \"cursor\": \"#708284\",\n    \"selection\": \"#595ab7\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"ashfinal\",\n          \"link\": \"https://github.com/ashfinal/vim-colors-violet\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Violet Light\",\n    \"black\": \"#56595c\",\n    \"red\": \"#c94c22\",\n    \"green\": \"#85981c\",\n    \"yellow\": \"#b4881d\",\n    \"blue\": \"#2e8bce\",\n    \"magenta\": \"#d13a82\",\n    \"cyan\": \"#32a198\",\n    \"white\": \"#d3d0c9\",\n    \"brightBlack\": \"#45484b\",\n    \"brightRed\": \"#bd3613\",\n    \"brightGreen\": \"#738a04\",\n    \"brightYellow\": \"#a57705\",\n    \"brightBlue\": \"#2176c7\",\n    \"brightMagenta\": \"#c61c6f\",\n    \"brightCyan\": \"#259286\",\n    \"brightWhite\": \"#c9c6bd\",\n    \"background\": \"#fcf4dc\",\n    \"foreground\": \"#536870\",\n    \"cursor\": \"#536870\",\n    \"selection\": \"#595ab7\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": [\n        {\n          \"name\": \"ashfinal\",\n          \"link\": \"https://github.com/ashfinal/vim-colors-violet\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"WarmNeon\",\n    \"black\": \"#000000\",\n    \"red\": \"#e24346\",\n    \"green\": \"#39b13a\",\n    \"yellow\": \"#dae145\",\n    \"blue\": \"#4261c5\",\n    \"magenta\": \"#f920fb\",\n    \"cyan\": \"#2abbd4\",\n    \"white\": \"#d0b8a3\",\n    \"brightBlack\": \"#fefcfc\",\n    \"brightRed\": \"#e97071\",\n    \"brightGreen\": \"#9cc090\",\n    \"brightYellow\": \"#ddda7a\",\n    \"brightBlue\": \"#7b91d6\",\n    \"brightMagenta\": \"#f674ba\",\n    \"brightCyan\": \"#5ed1e5\",\n    \"brightWhite\": \"#d8c8bb\",\n    \"background\": \"#404040\",\n    \"foreground\": \"#afdab6\",\n    \"cursor\": \"#30ff24\",\n    \"selection\": \"#b0ad21\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"PyCharm\",\n          \"link\": \"http://www.jetbrains.com/pycharm/\"\n        },\n        {\n          \"name\": \"firewut\",\n          \"link\": \"https://github.com/firewut\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Wez\",\n    \"black\": \"#000000\",\n    \"red\": \"#cc5555\",\n    \"green\": \"#55cc55\",\n    \"yellow\": \"#cdcd55\",\n    \"blue\": \"#5555cc\",\n    \"magenta\": \"#cc55cc\",\n    \"cyan\": \"#7acaca\",\n    \"white\": \"#cccccc\",\n    \"brightBlack\": \"#555555\",\n    \"brightRed\": \"#ff5555\",\n    \"brightGreen\": \"#55ff55\",\n    \"brightYellow\": \"#ffff55\",\n    \"brightBlue\": \"#5555ff\",\n    \"brightMagenta\": \"#ff55ff\",\n    \"brightCyan\": \"#55ffff\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#000000\",\n    \"foreground\": \"#b3b3b3\",\n    \"cursor\": \"#53ae71\",\n    \"selection\": \"#4d52f8\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"wez\",\n          \"link\": \"https://gist.github.com/wez/850268/\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Whimsy\",\n    \"black\": \"#535178\",\n    \"red\": \"#ef6487\",\n    \"green\": \"#5eca89\",\n    \"yellow\": \"#fdd877\",\n    \"blue\": \"#65aef7\",\n    \"magenta\": \"#aa7ff0\",\n    \"cyan\": \"#43c1be\",\n    \"white\": \"#ffffff\",\n    \"brightBlack\": \"#535178\",\n    \"brightRed\": \"#ef6487\",\n    \"brightGreen\": \"#5eca89\",\n    \"brightYellow\": \"#fdd877\",\n    \"brightBlue\": \"#65aef7\",\n    \"brightMagenta\": \"#aa7ff0\",\n    \"brightCyan\": \"#43c1be\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#29283b\",\n    \"foreground\": \"#b3b0d6\",\n    \"cursor\": \"#b3b0d6\",\n    \"selection\": \"#3d3c58\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Rod\",\n          \"link\": \"https://github.com/rod\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"WildCherry\",\n    \"black\": \"#000507\",\n    \"red\": \"#d94085\",\n    \"green\": \"#2ab250\",\n    \"yellow\": \"#ffd16f\",\n    \"blue\": \"#883cdc\",\n    \"magenta\": \"#ececec\",\n    \"cyan\": \"#c1b8b7\",\n    \"white\": \"#fff8de\",\n    \"brightBlack\": \"#009cc9\",\n    \"brightRed\": \"#da6bac\",\n    \"brightGreen\": \"#f4dca5\",\n    \"brightYellow\": \"#eac066\",\n    \"brightBlue\": \"#308cba\",\n    \"brightMagenta\": \"#ae636b\",\n    \"brightCyan\": \"#ff919d\",\n    \"brightWhite\": \"#e4838d\",\n    \"background\": \"#1f1726\",\n    \"foreground\": \"#dafaff\",\n    \"cursor\": \"#dd00ff\",\n    \"selection\": \"#002831\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"mashaal\",\n          \"link\": \"https://github.com/mashaal/wild-cherry\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"wilmersdorf\",\n    \"black\": \"#34373e\",\n    \"red\": \"#e06383\",\n    \"green\": \"#7ebebd\",\n    \"yellow\": \"#cccccc\",\n    \"blue\": \"#a6c1e0\",\n    \"magenta\": \"#e1c1ee\",\n    \"cyan\": \"#5b94ab\",\n    \"white\": \"#ababab\",\n    \"brightBlack\": \"#434750\",\n    \"brightRed\": \"#fa7193\",\n    \"brightGreen\": \"#8fd7d6\",\n    \"brightYellow\": \"#d1dfff\",\n    \"brightBlue\": \"#b2cff0\",\n    \"brightMagenta\": \"#efccfd\",\n    \"brightCyan\": \"#69abc5\",\n    \"brightWhite\": \"#d3d3d3\",\n    \"background\": \"#282b33\",\n    \"foreground\": \"#c6c6c6\",\n    \"cursor\": \"#7ebebd\",\n    \"selection\": \"#1f2024\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Wombat\",\n    \"black\": \"#000000\",\n    \"red\": \"#ff615a\",\n    \"green\": \"#b1e969\",\n    \"yellow\": \"#ebd99c\",\n    \"blue\": \"#5da9f6\",\n    \"magenta\": \"#e86aff\",\n    \"cyan\": \"#82fff7\",\n    \"white\": \"#dedacf\",\n    \"brightBlack\": \"#313131\",\n    \"brightRed\": \"#f58c80\",\n    \"brightGreen\": \"#ddf88f\",\n    \"brightYellow\": \"#eee5b2\",\n    \"brightBlue\": \"#a5c7ff\",\n    \"brightMagenta\": \"#ddaaff\",\n    \"brightCyan\": \"#b7fff9\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#171717\",\n    \"foreground\": \"#dedacf\",\n    \"cursor\": \"#bbbbbb\",\n    \"selection\": \"#453b39\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"djoyner\",\n          \"link\": \"https://github.com/djoyner/iTerm2-wombat\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"Wryan\",\n    \"black\": \"#333333\",\n    \"red\": \"#8c4665\",\n    \"green\": \"#287373\",\n    \"yellow\": \"#7c7c99\",\n    \"blue\": \"#395573\",\n    \"magenta\": \"#5e468c\",\n    \"cyan\": \"#31658c\",\n    \"white\": \"#899ca1\",\n    \"brightBlack\": \"#3d3d3d\",\n    \"brightRed\": \"#bf4d80\",\n    \"brightGreen\": \"#53a6a6\",\n    \"brightYellow\": \"#9e9ecb\",\n    \"brightBlue\": \"#477ab3\",\n    \"brightMagenta\": \"#7e62b3\",\n    \"brightCyan\": \"#6096bf\",\n    \"brightWhite\": \"#c0c0c0\",\n    \"background\": \"#101010\",\n    \"foreground\": \"#999993\",\n    \"cursor\": \"#9e9ecb\",\n    \"selection\": \"#4d4d4d\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"baskerville\",\n          \"link\": \"https://github.com/baskerville/iTerm-2-Color-Themes\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"zenbones\",\n    \"black\": \"#f0edec\",\n    \"red\": \"#a8334c\",\n    \"green\": \"#4f6c31\",\n    \"yellow\": \"#944927\",\n    \"blue\": \"#286486\",\n    \"magenta\": \"#88507d\",\n    \"cyan\": \"#3b8992\",\n    \"white\": \"#2c363c\",\n    \"brightBlack\": \"#cfc1ba\",\n    \"brightRed\": \"#94253e\",\n    \"brightGreen\": \"#3f5a22\",\n    \"brightYellow\": \"#803d1c\",\n    \"brightBlue\": \"#1d5573\",\n    \"brightMagenta\": \"#7b3b70\",\n    \"brightCyan\": \"#2b747c\",\n    \"brightWhite\": \"#4f5e68\",\n    \"background\": \"#f0edec\",\n    \"foreground\": \"#2c363c\",\n    \"cursor\": \"#2c363c\",\n    \"selection\": \"#cbd9e3\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"zenbones_dark\",\n    \"black\": \"#1c1917\",\n    \"red\": \"#de6e7c\",\n    \"green\": \"#819b69\",\n    \"yellow\": \"#b77e64\",\n    \"blue\": \"#6099c0\",\n    \"magenta\": \"#b279a7\",\n    \"cyan\": \"#66a5ad\",\n    \"white\": \"#b4bdc3\",\n    \"brightBlack\": \"#403833\",\n    \"brightRed\": \"#e8838f\",\n    \"brightGreen\": \"#8bae68\",\n    \"brightYellow\": \"#d68c67\",\n    \"brightBlue\": \"#61abda\",\n    \"brightMagenta\": \"#cf86c1\",\n    \"brightCyan\": \"#65b8c1\",\n    \"brightWhite\": \"#888f94\",\n    \"background\": \"#1c1917\",\n    \"foreground\": \"#b4bdc3\",\n    \"cursor\": \"#c4cacf\",\n    \"selection\": \"#3d4042\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"zenbones_light\",\n    \"black\": \"#f0edec\",\n    \"red\": \"#a8334c\",\n    \"green\": \"#4f6c31\",\n    \"yellow\": \"#944927\",\n    \"blue\": \"#286486\",\n    \"magenta\": \"#88507d\",\n    \"cyan\": \"#3b8992\",\n    \"white\": \"#2c363c\",\n    \"brightBlack\": \"#cfc1ba\",\n    \"brightRed\": \"#94253e\",\n    \"brightGreen\": \"#3f5a22\",\n    \"brightYellow\": \"#803d1c\",\n    \"brightBlue\": \"#1d5573\",\n    \"brightMagenta\": \"#7b3b70\",\n    \"brightCyan\": \"#2b747c\",\n    \"brightWhite\": \"#4f5e68\",\n    \"background\": \"#f0edec\",\n    \"foreground\": \"#2c363c\",\n    \"cursor\": \"#2c363c\",\n    \"selection\": \"#cbd9e3\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"Zenburn\",\n    \"black\": \"#4d4d4d\",\n    \"red\": \"#705050\",\n    \"green\": \"#60b48a\",\n    \"yellow\": \"#f0dfaf\",\n    \"blue\": \"#506070\",\n    \"magenta\": \"#dc8cc3\",\n    \"cyan\": \"#8cd0d3\",\n    \"white\": \"#dcdccc\",\n    \"brightBlack\": \"#709080\",\n    \"brightRed\": \"#dca3a3\",\n    \"brightGreen\": \"#c3bf9f\",\n    \"brightYellow\": \"#e0cf9f\",\n    \"brightBlue\": \"#94bff3\",\n    \"brightMagenta\": \"#ec93d3\",\n    \"brightCyan\": \"#93e0e3\",\n    \"brightWhite\": \"#ffffff\",\n    \"background\": \"#3f3f3f\",\n    \"foreground\": \"#dcdccc\",\n    \"cursor\": \"#73635a\",\n    \"selection\": \"#21322f\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": [\n        {\n          \"name\": \"Zenburn\",\n          \"link\": \"http://sunaku.github.io/zenburn-terminal-color-scheme.html\"\n        }\n      ]\n    }\n  },\n  {\n    \"name\": \"zenburned\",\n    \"black\": \"#404040\",\n    \"red\": \"#e3716e\",\n    \"green\": \"#819b69\",\n    \"yellow\": \"#b77e64\",\n    \"blue\": \"#6099c0\",\n    \"magenta\": \"#b279a7\",\n    \"cyan\": \"#66a5ad\",\n    \"white\": \"#f0e4cf\",\n    \"brightBlack\": \"#625a5b\",\n    \"brightRed\": \"#ec8685\",\n    \"brightGreen\": \"#8bae68\",\n    \"brightYellow\": \"#d68c67\",\n    \"brightBlue\": \"#61abda\",\n    \"brightMagenta\": \"#cf86c1\",\n    \"brightCyan\": \"#65b8c1\",\n    \"brightWhite\": \"#c0ab86\",\n    \"background\": \"#404040\",\n    \"foreground\": \"#f0e4cf\",\n    \"cursor\": \"#f3eadb\",\n    \"selection\": \"#746956\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"zenwritten_dark\",\n    \"black\": \"#191919\",\n    \"red\": \"#de6e7c\",\n    \"green\": \"#819b69\",\n    \"yellow\": \"#b77e64\",\n    \"blue\": \"#6099c0\",\n    \"magenta\": \"#b279a7\",\n    \"cyan\": \"#66a5ad\",\n    \"white\": \"#bbbbbb\",\n    \"brightBlack\": \"#3d3839\",\n    \"brightRed\": \"#e8838f\",\n    \"brightGreen\": \"#8bae68\",\n    \"brightYellow\": \"#d68c67\",\n    \"brightBlue\": \"#61abda\",\n    \"brightMagenta\": \"#cf86c1\",\n    \"brightCyan\": \"#65b8c1\",\n    \"brightWhite\": \"#8e8e8e\",\n    \"background\": \"#191919\",\n    \"foreground\": \"#bbbbbb\",\n    \"cursor\": \"#c9c9c9\",\n    \"selection\": \"#404040\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  },\n  {\n    \"name\": \"zenwritten_light\",\n    \"black\": \"#eeeeee\",\n    \"red\": \"#a8334c\",\n    \"green\": \"#4f6c31\",\n    \"yellow\": \"#944927\",\n    \"blue\": \"#286486\",\n    \"magenta\": \"#88507d\",\n    \"cyan\": \"#3b8992\",\n    \"white\": \"#353535\",\n    \"brightBlack\": \"#c6c3c3\",\n    \"brightRed\": \"#94253e\",\n    \"brightGreen\": \"#3f5a22\",\n    \"brightYellow\": \"#803d1c\",\n    \"brightBlue\": \"#1d5573\",\n    \"brightMagenta\": \"#7b3b70\",\n    \"brightCyan\": \"#2b747c\",\n    \"brightWhite\": \"#5c5c5c\",\n    \"background\": \"#eeeeee\",\n    \"foreground\": \"#353535\",\n    \"cursor\": \"#353535\",\n    \"selection\": \"#d7d7d7\",\n    \"meta\": {\n      \"isDark\": false,\n      \"credits\": null\n    }\n  },\n  {\n    \"background\": \"#01001D\",\n    \"black\": \"#0C0C0C\",\n    \"blue\": \"#3E31F5\",\n    \"brightBlack\": \"#686868\",\n    \"brightBlue\": \"#737CFF\",\n    \"brightCyan\": \"#7FFFFF\",\n    \"brightGreen\": \"#6BFF6B\",\n    \"brightMagenta\": \"#FF70FF\",\n    \"brightRed\": \"#FF6E6E\",\n    \"brightWhite\": \"#FFFFFF\",\n    \"brightYellow\": \"#FFFF6B\",\n    \"cursor\": \"#FFFFFF\",\n    \"cyan\": \"#13D4D4\",\n    \"foreground\": \"#FFFFFF\",\n    \"green\": \"#21C221\",\n    \"name\": \"Zeonica\",\n    \"magenta\": \"#D918B9\",\n    \"red\": \"#CC2929\",\n    \"selection\": \"#242272\",\n    \"white\": \"#B2B2B2\",\n    \"yellow\": \"#D6C315\",\n    \"meta\": {\n      \"isDark\": true,\n      \"credits\": null\n    }\n  }\n]\n"
  },
  {
    "path": "themes_test.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n)\n\nfunc TestFindAllThemes(t *testing.T) {\n\tthemes, err := sortedThemeNames()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\texpect := 348\n\tif l := len(themes); l != expect {\n\t\tt.Errorf(\"expected to load %d themes, got %d\", expect, l)\n\t}\n}\n\nfunc TestFindTheme(t *testing.T) {\n\ttests := []struct {\n\t\ttname string\n\t\ttheme string\n\t\terr   error\n\t}{\n\t\t{\n\t\t\ttname: \"exact match\",\n\t\t\ttheme: \"Catppuccin Latte\",\n\t\t\terr:   nil,\n\t\t},\n\t\t{\n\t\t\ttname: \"match found\",\n\t\t\ttheme: \"caTppuccin ltt\",\n\t\t\terr:   ThemeNotFoundError{\"caTppuccin ltt\", []string{\"Catppuccin Latte\"}},\n\t\t},\n\t\t{\n\t\t\ttname: \"no match found\",\n\t\t\ttheme: \"stArf1sh\",\n\t\t\terr:   ThemeNotFoundError{\"stArf1sh\", []string{}},\n\t\t},\n\t\t{\n\t\t\ttname: \"single char\",\n\t\t\ttheme: \"s\",\n\t\t\terr:   ThemeNotFoundError{\"s\", []string{}},\n\t\t},\n\t\t{\n\t\t\ttname: \"empty string\",\n\t\t\ttheme: \"\",\n\t\t\terr:   ThemeNotFoundError{\"\", []string{}},\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.tname, func(t *testing.T) {\n\t\t\t_, err := findTheme(tc.theme)\n\t\t\tif tc.err != nil {\n\t\t\t\tif err == nil {\n\t\t\t\t\tt.Fatal(\"expected an error:\", tc.err)\n\t\t\t\t}\n\t\t\t\t// check we got the right error\n\t\t\t\tvar perr ThemeNotFoundError\n\t\t\t\tif !errors.As(err, &perr) {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tgotErr := err.(ThemeNotFoundError)\n\t\t\t\twantErr := tc.err.(ThemeNotFoundError)\n\t\t\t\t// check suggestions\n\t\t\t\tsort.Strings(gotErr.Suggestions)\n\t\t\t\tsort.Strings(wantErr.Suggestions)\n\t\t\t\tif !reflect.DeepEqual(gotErr.Suggestions, wantErr.Suggestions) {\n\t\t\t\t\tt.Fatalf(\"got != want. got: %v, want: %v\", err, tc.err)\n\t\t\t\t}\n\t\t\t\t// check names\n\t\t\t\tif !reflect.DeepEqual(gotErr.Theme, wantErr.Theme) {\n\t\t\t\t\tt.Fatalf(\"got != want. got: %v, want: %v\", err, tc.err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif err != nil && tc.err == nil {\n\t\t\t\tt.Fatal(\"unexpected error:\", err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "token/token.go",
    "content": "// Package token provides the token types and structures for the VHS Tape\n// language.\npackage token\n\nimport (\n\t\"strings\"\n)\n\n// Type represents a token's type.\ntype Type string\n\n// Token represents a lexer token.\ntype Token struct {\n\tType    Type\n\tLiteral string\n\tLine    int\n\tColumn  int\n}\n\n// Tokens for the VHS language.\nconst (\n\tAT        = \"@\"\n\tEQUAL     = \"=\"\n\tPLUS      = \"+\"\n\tPERCENT   = \"%\"\n\tSLASH     = \"/\"\n\tBACKSLASH = \"\\\\\"\n\tDOT       = \".\"\n\tDASH      = \"-\"\n\n\tMINUS         = \"-\"\n\tRIGHT_BRACKET = \"]\"\n\tLEFT_BRACKET  = \"[\"\n\tCARET         = \"^\"\n\n\tEM           = \"EM\"\n\tMILLISECONDS = \"MILLISECONDS\"\n\tMINUTES      = \"MINUTES\"\n\tPX           = \"PX\"\n\tSECONDS      = \"SECONDS\"\n\n\tEOF     = \"EOF\"\n\tILLEGAL = \"ILLEGAL\"\n\n\tALT         = \"ALT\"\n\tBACKSPACE   = \"BACKSPACE\"\n\tCTRL        = \"CTRL\"\n\tDELETE      = \"DELETE\"\n\tEND         = \"END\"\n\tENTER       = \"ENTER\"\n\tESCAPE      = \"ESCAPE\"\n\tHOME        = \"HOME\"\n\tINSERT      = \"INSERT\"\n\tPAGE_DOWN   = \"PAGE_DOWN\"\n\tPAGE_UP     = \"PAGE_UP\"\n\tSCROLL_DOWN = \"SCROLL_DOWN\"\n\tSCROLL_UP   = \"SCROLL_UP\"\n\tSLEEP       = \"SLEEP\"\n\tSPACE       = \"SPACE\"\n\tTAB         = \"TAB\"\n\tSHIFT       = \"SHIFT\"\n\n\tCOMMENT = \"COMMENT\"\n\tNUMBER  = \"NUMBER\"\n\tSTRING  = \"STRING\"\n\tJSON    = \"JSON\"\n\tREGEX   = \"REGEX\"\n\tBOOLEAN = \"BOOLEAN\"\n\n\tDOWN  = \"DOWN\"\n\tLEFT  = \"LEFT\"\n\tRIGHT = \"RIGHT\"\n\tUP    = \"UP\"\n\n\tHIDE            = \"HIDE\"\n\tOUTPUT          = \"OUTPUT\"\n\tREQUIRE         = \"REQUIRE\"\n\tSET             = \"SET\"\n\tSHOW            = \"SHOW\"\n\tSOURCE          = \"SOURCE\"\n\tTYPE            = \"TYPE\"\n\tSCREENSHOT      = \"SCREENSHOT\"\n\tCOPY            = \"COPY\"\n\tPASTE           = \"PASTE\"\n\tSHELL           = \"SHELL\"\n\tENV             = \"ENV\"\n\tFONT_FAMILY     = \"FONT_FAMILY\"\n\tFONT_SIZE       = \"FONT_SIZE\"\n\tFRAMERATE       = \"FRAMERATE\"\n\tPLAYBACK_SPEED  = \"PLAYBACK_SPEED\"\n\tHEIGHT          = \"HEIGHT\"\n\tWIDTH           = \"WIDTH\"\n\tLETTER_SPACING  = \"LETTER_SPACING\"\n\tLINE_HEIGHT     = \"LINE_HEIGHT\"\n\tTYPING_SPEED    = \"TYPING_SPEED\"\n\tPADDING         = \"PADDING\"\n\tTHEME           = \"THEME\"\n\tLOOP_OFFSET     = \"LOOP_OFFSET\"\n\tMARGIN_FILL     = \"MARGIN_FILL\"\n\tMARGIN          = \"MARGIN\"\n\tWINDOW_BAR      = \"WINDOW_BAR\"\n\tWINDOW_BAR_SIZE = \"WINDOW_BAR_SIZE\"\n\tBORDER_RADIUS   = \"CORNER_RADIUS\"\n\tWAIT            = \"WAIT\"\n\tWAIT_TIMEOUT    = \"WAIT_TIMEOUT\"\n\tWAIT_PATTERN    = \"WAIT_PATTERN\"\n\tCURSOR_BLINK    = \"CURSOR_BLINK\"\n)\n\n// Keywords maps keyword strings to tokens.\nvar Keywords = map[string]Type{\n\t\"em\":            EM,\n\t\"px\":            PX,\n\t\"ms\":            MILLISECONDS,\n\t\"s\":             SECONDS,\n\t\"m\":             MINUTES,\n\t\"Set\":           SET,\n\t\"Sleep\":         SLEEP,\n\t\"Type\":          TYPE,\n\t\"Enter\":         ENTER,\n\t\"Space\":         SPACE,\n\t\"Backspace\":     BACKSPACE,\n\t\"Delete\":        DELETE,\n\t\"Insert\":        INSERT,\n\t\"Ctrl\":          CTRL,\n\t\"Alt\":           ALT,\n\t\"Shift\":         SHIFT,\n\t\"Down\":          DOWN,\n\t\"Left\":          LEFT,\n\t\"Right\":         RIGHT,\n\t\"Up\":            UP,\n\t\"PageUp\":        PAGE_UP,\n\t\"PageDown\":      PAGE_DOWN,\n\t\"ScrollUp\":      SCROLL_UP,\n\t\"ScrollDown\":    SCROLL_DOWN,\n\t\"Tab\":           TAB,\n\t\"Escape\":        ESCAPE,\n\t\"End\":           END,\n\t\"Hide\":          HIDE,\n\t\"Require\":       REQUIRE,\n\t\"Show\":          SHOW,\n\t\"Output\":        OUTPUT,\n\t\"Shell\":         SHELL,\n\t\"FontFamily\":    FONT_FAMILY,\n\t\"MarginFill\":    MARGIN_FILL,\n\t\"Margin\":        MARGIN,\n\t\"WindowBar\":     WINDOW_BAR,\n\t\"WindowBarSize\": WINDOW_BAR_SIZE,\n\t\"BorderRadius\":  BORDER_RADIUS,\n\t\"FontSize\":      FONT_SIZE,\n\t\"Framerate\":     FRAMERATE,\n\t\"Height\":        HEIGHT,\n\t\"LetterSpacing\": LETTER_SPACING,\n\t\"LineHeight\":    LINE_HEIGHT,\n\t\"PlaybackSpeed\": PLAYBACK_SPEED,\n\t\"TypingSpeed\":   TYPING_SPEED,\n\t\"Padding\":       PADDING,\n\t\"Theme\":         THEME,\n\t\"Width\":         WIDTH,\n\t\"LoopOffset\":    LOOP_OFFSET,\n\t\"WaitTimeout\":   WAIT_TIMEOUT,\n\t\"WaitPattern\":   WAIT_PATTERN,\n\t\"Wait\":          WAIT,\n\t\"Source\":        SOURCE,\n\t\"CursorBlink\":   CURSOR_BLINK,\n\t\"true\":          BOOLEAN,\n\t\"false\":         BOOLEAN,\n\t\"Screenshot\":    SCREENSHOT,\n\t\"Copy\":          COPY,\n\t\"Paste\":         PASTE,\n\t\"Env\":           ENV,\n}\n\n// IsSetting returns whether a token is a setting.\nfunc IsSetting(t Type) bool {\n\tswitch t {\n\tcase SHELL, FONT_FAMILY, FONT_SIZE, LETTER_SPACING, LINE_HEIGHT,\n\t\tFRAMERATE, TYPING_SPEED, THEME, PLAYBACK_SPEED, HEIGHT, WIDTH,\n\t\tPADDING, LOOP_OFFSET, MARGIN_FILL, MARGIN, WINDOW_BAR,\n\t\tWINDOW_BAR_SIZE, BORDER_RADIUS, CURSOR_BLINK, WAIT_TIMEOUT, WAIT_PATTERN:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// IsCommand returns whether the string is a command.\nfunc IsCommand(t Type) bool {\n\tswitch t {\n\tcase TYPE, SLEEP,\n\t\tUP, DOWN, RIGHT, LEFT, PAGE_UP, PAGE_DOWN, SCROLL_UP, SCROLL_DOWN,\n\t\tENTER, BACKSPACE, DELETE, TAB,\n\t\tESCAPE, HOME, INSERT, END, CTRL, SOURCE, SCREENSHOT, COPY, PASTE, WAIT:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// IsModifier returns whether the token is a modifier.\nfunc IsModifier(t Type) bool {\n\treturn t == ALT || t == SHIFT\n}\n\n// String converts a token to it's human readable string format.\nfunc (t Type) String() string {\n\tif IsCommand(t) || IsSetting(t) {\n\t\treturn ToCamel(string(t))\n\t}\n\treturn string(t)\n}\n\n// ToCamel converts a snake_case string to CamelCase.\nfunc ToCamel(s string) string {\n\tparts := strings.Split(s, \"_\")\n\tfor i, p := range parts {\n\t\tp = strings.ToUpper(p[:1]) + strings.ToLower(p[1:])\n\t\tparts[i] = p\n\t}\n\n\treturn strings.Join(parts, \"\")\n}\n\n// LookupIdentifier returns whether the identifier is a keyword.\n// In `vhs`, there are no _actual_ identifiers, i.e. there are no variables.\n// Instead, identifiers are simply strings (i.e. bare words).\nfunc LookupIdentifier(ident string) Type {\n\tif t, ok := Keywords[ident]; ok {\n\t\treturn t\n\t}\n\treturn STRING\n}\n"
  },
  {
    "path": "token/token_test.go",
    "content": "package token\n\nimport \"testing\"\n\nfunc TestToCamel(t *testing.T) {\n\t// simple case\n\tres := ToCamel(\"SIMPLE\")\n\tif res != \"Simple\" {\n\t\tt.Errorf(\"expected Simple, got %s\", res)\n\t}\n\n\t// multiple words\n\tres = ToCamel(\"MULTIPLE_WORDS\")\n\tif res != \"MultipleWords\" {\n\t\tt.Errorf(\"expected MultipleWords, got %s\", res)\n\t}\n}\n"
  },
  {
    "path": "tty.go",
    "content": "// Package vhs tty.go spawns the ttyd process.\n// It runs on the specified port and is generally meant to run in the background\n// so that other processes (go-rod) can connect to the tty.\n//\n// xterm.js is used for rendering the terminal and can be adjusted using the Set command.\n//\n// Set FontFamily \"DejaVu Sans Mono\"\n// Set FontSize 12\n// Set Padding 50\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"os/exec\"\n)\n\n// randomPort returns a random port number that is not in use.\nfunc randomPort() int {\n\taddr, _ := net.Listen(\"tcp\", \":0\") //nolint:gosec,noctx\n\t_ = addr.Close()\n\treturn addr.Addr().(*net.TCPAddr).Port\n}\n\n// buildTtyCmd builds the ttyd exec.Command on the given port.\nfunc buildTtyCmd(port int, shell Shell) *exec.Cmd {\n\targs := []string{ //nolint:prealloc\n\t\tfmt.Sprintf(\"--port=%d\", port),\n\t\t\"--interface\", \"127.0.0.1\",\n\t\t\"-t\", \"rendererType=canvas\",\n\t\t\"-t\", \"disableResizeOverlay=true\",\n\t\t\"-t\", \"enableSixel=true\",\n\t\t\"-t\", \"customGlyphs=true\",\n\t\t\"--once\", // will allow one connection and exit\n\t\t\"--writable\",\n\t}\n\n\targs = append(args, shell.Command...)\n\n\tcmd := exec.Command(\"ttyd\", args...)\n\tif shell.Env != nil {\n\t\tcmd.Env = append(shell.Env, os.Environ()...)\n\t}\n\treturn cmd\n}\n"
  },
  {
    "path": "tty_unix.go",
    "content": "//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris\n// +build darwin dragonfly freebsd linux netbsd openbsd solaris\n\npackage main\n\nconst defaultShell = bash\n"
  },
  {
    "path": "tty_windows.go",
    "content": "//go:build windows\n// +build windows\n\npackage main\n\nvar defaultShell = cmdexe\n"
  },
  {
    "path": "vhs.go",
    "content": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"math\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/go-rod/rod\"\n\t\"github.com/go-rod/rod/lib/launcher\"\n\t\"github.com/go-rod/rod/lib/proto\"\n)\n\n// VHS is the object that controls the setup.\ntype VHS struct {\n\tOptions      *Options\n\tErrors       []error\n\tPage         *rod.Page\n\tbrowser      *rod.Browser\n\tTextCanvas   *rod.Element\n\tCursorCanvas *rod.Element\n\tmutex        *sync.Mutex\n\tstarted      bool\n\trecording    bool\n\ttty          *exec.Cmd\n\ttotalFrames  int\n\tclose        func() error\n}\n\n// Options is the set of options for the setup.\ntype Options struct {\n\tShell         Shell\n\tFontFamily    string\n\tFontSize      int\n\tLetterSpacing float64\n\tLineHeight    float64\n\tTypingSpeed   time.Duration\n\tTheme         Theme\n\tTest          TestOptions\n\tVideo         VideoOptions\n\tLoopOffset    float64\n\tWaitTimeout   time.Duration\n\tWaitPattern   *regexp.Regexp\n\tCursorBlink   bool\n\tScreenshot    ScreenshotOptions\n\tStyle         StyleOptions\n}\n\nconst (\n\tdefaultFontSize      = 22\n\tdefaultTypingSpeed   = 50 * time.Millisecond\n\tdefaultLineHeight    = 1.0\n\tdefaultLetterSpacing = 1.0\n\tfontsSeparator       = \",\"\n\tdefaultCursorBlink   = true\n\tdefaultWaitTimeout   = 15 * time.Second\n)\n\nvar defaultWaitPattern = regexp.MustCompile(\">$\")\n\nvar defaultFontFamily = withSymbolsFallback(strings.Join([]string{\n\t\"JetBrains Mono\",\n\t\"DejaVu Sans Mono\",\n\t\"Menlo\",\n\t\"Bitstream Vera Sans Mono\",\n\t\"Inconsolata\",\n\t\"Roboto Mono\",\n\t\"Hack\",\n\t\"Consolas\",\n\t\"ui-monospace\",\n\t\"monospace\",\n}, fontsSeparator))\n\nvar symbolsFallback = []string{\n\t\"Apple Symbols\",\n}\n\nfunc withSymbolsFallback(font string) string {\n\treturn font + fontsSeparator + strings.Join(symbolsFallback, fontsSeparator)\n}\n\n// DefaultVHSOptions returns the default set of options to use for the setup function.\nfunc DefaultVHSOptions() Options {\n\tstyle := DefaultStyleOptions()\n\tvideo := DefaultVideoOptions()\n\tvideo.Style = style\n\tscreenshot := NewScreenshotOptions(video.Input, style)\n\n\treturn Options{\n\t\tFontFamily:    defaultFontFamily,\n\t\tFontSize:      defaultFontSize,\n\t\tLetterSpacing: defaultLetterSpacing,\n\t\tLineHeight:    defaultLineHeight,\n\t\tTypingSpeed:   defaultTypingSpeed,\n\t\tShell:         Shells[defaultShell],\n\t\tTheme:         DefaultTheme,\n\t\tCursorBlink:   defaultCursorBlink,\n\t\tVideo:         video,\n\t\tScreenshot:    screenshot,\n\t\tWaitTimeout:   defaultWaitTimeout,\n\t\tWaitPattern:   defaultWaitPattern,\n\t}\n}\n\n// New sets up ttyd and go-rod for recording frames.\nfunc New() VHS {\n\tmu := &sync.Mutex{}\n\topts := DefaultVHSOptions()\n\treturn VHS{\n\t\tOptions:   &opts,\n\t\trecording: true,\n\t\tmutex:     mu,\n\t}\n}\n\n// Start starts ttyd, browser and everything else needed to create the gif.\nfunc (vhs *VHS) Start() error {\n\tvhs.mutex.Lock()\n\tdefer vhs.mutex.Unlock()\n\n\tif vhs.started {\n\t\treturn fmt.Errorf(\"vhs is already started\")\n\t}\n\n\tport := randomPort()\n\tvhs.tty = buildTtyCmd(port, vhs.Options.Shell)\n\tif err := vhs.tty.Start(); err != nil {\n\t\treturn fmt.Errorf(\"could not start tty: %w\", err)\n\t}\n\n\tpath, _ := launcher.LookPath()\n\tenableNoSandbox := os.Getenv(\"VHS_NO_SANDBOX\") != \"\"\n\tu, err := launcher.New().Leakless(false).Bin(path).NoSandbox(enableNoSandbox).Launch()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not launch browser: %w\", err)\n\t}\n\tbrowser := rod.New().ControlURL(u).MustConnect()\n\tpage, err := browser.Page(proto.TargetCreateTarget{URL: fmt.Sprintf(\"http://localhost:%d\", port)})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not open ttyd: %w\", err)\n\t}\n\n\tvhs.browser = browser\n\tvhs.Page = page\n\tvhs.close = vhs.browser.Close\n\tvhs.started = true\n\treturn nil\n}\n\n// Setup sets up the VHS instance and performs the necessary actions to reflect\n// the options that are default and set by the user.\nfunc (vhs *VHS) Setup() {\n\t// Set Viewport to the correct size, accounting for the padding that will be\n\t// added during the render.\n\tpadding := vhs.Options.Video.Style.Padding\n\tmargin := 0\n\tif vhs.Options.Video.Style.MarginFill != \"\" {\n\t\tmargin = vhs.Options.Video.Style.Margin\n\t}\n\tbar := 0\n\tif vhs.Options.Video.Style.WindowBar != \"\" {\n\t\tbar = vhs.Options.Video.Style.WindowBarSize\n\t}\n\twidth := vhs.Options.Video.Style.Width - double(padding) - double(margin)\n\theight := vhs.Options.Video.Style.Height - double(padding) - double(margin) - bar\n\tvhs.Page = vhs.Page.MustSetViewport(width, height, 0, false)\n\n\t// Find xterm.js canvases for the text and cursor layer for recording.\n\tvhs.TextCanvas, _ = vhs.Page.Element(\"canvas.xterm-text-layer\")\n\tvhs.CursorCanvas, _ = vhs.Page.Element(\"canvas.xterm-cursor-layer\")\n\n\t// Apply options to the terminal\n\t// By this point the setting commands have been executed, so the `opts` struct is up to date.\n\tvhs.Page.MustEval(fmt.Sprintf(\"() => { term.options = { fontSize: %d, fontFamily: '%s', letterSpacing: %f, lineHeight: %f, theme: %s, cursorBlink: %t } }\",\n\t\tvhs.Options.FontSize, vhs.Options.FontFamily, vhs.Options.LetterSpacing,\n\t\tvhs.Options.LineHeight, vhs.Options.Theme.String(), vhs.Options.CursorBlink))\n\n\t// Fit the terminal into the window\n\tvhs.Page.MustEval(\"term.fit\")\n\n\t_ = os.RemoveAll(vhs.Options.Video.Input)\n\t_ = os.MkdirAll(vhs.Options.Video.Input, 0o750)\n}\n\nconst cleanupWaitTime = 100 * time.Millisecond\n\n// Terminate cleans up a VHS instance and terminates the go-rod browser and ttyd\n// processes.\n//\n//nolint:wrapcheck\nfunc (vhs *VHS) terminate() error {\n\t// Give some time for any commands executed (such as `rm`) to finish.\n\t//\n\t// If a user runs a long running command, they must sleep for the required time\n\t// to finish.\n\ttime.Sleep(cleanupWaitTime)\n\n\t// Tear down the processes we started.\n\tvhs.browser.MustClose()\n\treturn vhs.tty.Process.Kill()\n}\n\n// Cleanup individual frames.\n//\n//nolint:wrapcheck\nfunc (vhs *VHS) Cleanup() error {\n\terr := os.RemoveAll(vhs.Options.Video.Input)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn os.RemoveAll(vhs.Options.Screenshot.input)\n}\n\n// Render starts rendering the individual frames into a video.\nfunc (vhs *VHS) Render() error {\n\t// Apply Loop Offset by modifying frame sequence\n\tif err := vhs.ApplyLoopOffset(); err != nil {\n\t\treturn err\n\t}\n\n\t// Generate the video(s) with the frames.\n\tvar cmds []*exec.Cmd //nolint:prealloc\n\tcmds = append(cmds, MakeGIF(vhs.Options.Video))\n\tcmds = append(cmds, MakeMP4(vhs.Options.Video))\n\tcmds = append(cmds, MakeWebM(vhs.Options.Video))\n\tcmds = append(cmds, MakeScreenshots(vhs.Options.Screenshot)...)\n\n\tfor _, cmd := range cmds {\n\t\tif cmd == nil {\n\t\t\tcontinue\n\t\t}\n\t\tout, err := cmd.CombinedOutput()\n\t\tif err != nil {\n\t\t\tlog.Println(string(out))\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// ApplyLoopOffset by modifying frame sequence.\nfunc (vhs *VHS) ApplyLoopOffset() error {\n\tif vhs.totalFrames <= 0 {\n\t\treturn errors.New(\"no frames\")\n\t}\n\n\tloopOffsetPercentage := vhs.Options.LoopOffset\n\n\t// Calculate # of frames to offset from LoopOffset percentage\n\tloopOffsetFrames := int(math.Ceil(loopOffsetPercentage / 100.0 * float64(vhs.totalFrames)))\n\n\t// Take care of overflow and keep track of exact offsetPercentage\n\tloopOffsetFrames = loopOffsetFrames % vhs.totalFrames\n\n\t// No operation if nothing to offset\n\tif loopOffsetFrames <= 0 {\n\t\treturn nil\n\t}\n\n\t// Move all frames in [offsetStart, offsetEnd] to end of frame sequence\n\toffsetStart := vhs.Options.Video.StartingFrame\n\toffsetEnd := loopOffsetFrames\n\n\t// New starting frame will be the next frame after offsetEnd\n\tvhs.Options.Video.StartingFrame = offsetEnd + 1\n\n\t// Rename all text and cursor frame files in the range concurrently\n\terrCh := make(chan error)\n\tdoneCh := make(chan bool)\n\tvar wg sync.WaitGroup\n\n\tfor counter := offsetStart; counter <= offsetEnd; counter++ {\n\t\twg.Add(1)\n\t\tgo func(frameNum int) {\n\t\t\tdefer wg.Done()\n\t\t\toffsetFrameNum := frameNum + vhs.totalFrames\n\t\t\tif err := os.Rename(\n\t\t\t\tfilepath.Join(vhs.Options.Video.Input, fmt.Sprintf(cursorFrameFormat, frameNum)),\n\t\t\t\tfilepath.Join(vhs.Options.Video.Input, fmt.Sprintf(cursorFrameFormat, offsetFrameNum)),\n\t\t\t); err != nil {\n\t\t\t\terrCh <- fmt.Errorf(\"error applying offset to cursor frame: %w\", err)\n\t\t\t}\n\t\t}(counter)\n\n\t\twg.Add(1)\n\t\tgo func(frameNum int) {\n\t\t\tdefer wg.Done()\n\t\t\toffsetFrameNum := frameNum + vhs.totalFrames\n\t\t\tif err := os.Rename(\n\t\t\t\tfilepath.Join(vhs.Options.Video.Input, fmt.Sprintf(textFrameFormat, frameNum)),\n\t\t\t\tfilepath.Join(vhs.Options.Video.Input, fmt.Sprintf(textFrameFormat, offsetFrameNum)),\n\t\t\t); err != nil {\n\t\t\t\terrCh <- fmt.Errorf(\"error applying offset to text frame: %w\", err)\n\t\t\t}\n\t\t}(counter)\n\t}\n\n\tgo func() {\n\t\twg.Wait()\n\t\tclose(doneCh)\n\t}()\n\n\tselect {\n\tcase <-doneCh:\n\t\treturn nil\n\tcase err := <-errCh:\n\t\t// Bail out in case of an error while renaming\n\t\treturn err\n\t}\n}\n\nconst quality = 1.0\n\n// Record begins the goroutine which captures images from the xterm.js canvases.\nfunc (vhs *VHS) Record(ctx context.Context) <-chan error {\n\tch := make(chan error)\n\tinterval := time.Second / time.Duration(vhs.Options.Video.Framerate)\n\n\t//nolint: mnd\n\tgo func() {\n\t\tcounter := 0\n\t\tstart := time.Now()\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\t_ = vhs.terminate()\n\n\t\t\t\t// Save total # of frames for offset calculation\n\t\t\t\tvhs.totalFrames = counter\n\n\t\t\t\t// Signal caller that we're done recording.\n\t\t\t\tclose(ch)\n\t\t\t\treturn\n\n\t\t\tcase <-time.After(interval - time.Since(start)):\n\t\t\t\t// record last attempt\n\t\t\t\tstart = time.Now()\n\n\t\t\t\tif !vhs.recording {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif vhs.Page == nil {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tcursor, cursorErr := vhs.CursorCanvas.CanvasToImage(\"image/png\", quality)\n\t\t\t\ttext, textErr := vhs.TextCanvas.CanvasToImage(\"image/png\", quality)\n\t\t\t\tif textErr != nil || cursorErr != nil {\n\t\t\t\t\tch <- fmt.Errorf(\"error: %v, %v\", textErr, cursorErr)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tcounter++\n\t\t\t\tif err := os.WriteFile(\n\t\t\t\t\tfilepath.Join(vhs.Options.Video.Input, fmt.Sprintf(cursorFrameFormat, counter)),\n\t\t\t\t\tcursor,\n\t\t\t\t\t0o600,\n\t\t\t\t); err != nil {\n\t\t\t\t\tch <- fmt.Errorf(\"error writing cursor frame: %w\", err)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif err := os.WriteFile(\n\t\t\t\t\tfilepath.Join(vhs.Options.Video.Input, fmt.Sprintf(textFrameFormat, counter)),\n\t\t\t\t\ttext,\n\t\t\t\t\t0o600,\n\t\t\t\t); err != nil {\n\t\t\t\t\tch <- fmt.Errorf(\"error writing text frame: %w\", err)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Capture current frame and disable frame capturing\n\t\t\t\tif vhs.Options.Screenshot.frameCapture {\n\t\t\t\t\tvhs.Options.Screenshot.makeScreenshot(counter)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}()\n\n\treturn ch\n}\n\n// ResumeRecording indicates to VHS that the recording should be resumed.\nfunc (vhs *VHS) ResumeRecording() {\n\tvhs.mutex.Lock()\n\tdefer vhs.mutex.Unlock()\n\n\tvhs.recording = true\n}\n\n// PauseRecording indicates to VHS that the recording should be paused.\nfunc (vhs *VHS) PauseRecording() {\n\tvhs.mutex.Lock()\n\tdefer vhs.mutex.Unlock()\n\n\tvhs.recording = false\n}\n\n// ScreenshotNextFrame indicates to VHS that screenshot of next frame must be taken.\nfunc (vhs *VHS) ScreenshotNextFrame(path string) {\n\tvhs.mutex.Lock()\n\tdefer vhs.mutex.Unlock()\n\n\tvhs.Options.Screenshot.enableFrameCapture(path)\n}\n"
  },
  {
    "path": "video.go",
    "content": "// Package vhs video.go spawns the ffmpeg process to convert the frames,\n// collected by go-rod's  screenshots into the input folder, to a GIF, WebM,\n// MP4.\n//\n// MakeGIF takes several options to modify the behaviour of the ffmpeg process,\n// which can be configured through the Set command.\n//\n// Set MaxColors 256\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nconst (\n\ttextFrameFormat   = \"frame-text-%05d.png\"\n\tcursorFrameFormat = \"frame-cursor-%05d.png\"\n)\n\nconst (\n\tmp4  = \".mp4\"\n\twebm = \".webm\"\n\tgif  = \".gif\"\n)\n\n// randomDir returns a random temporary directory to be used for storing frames\n// from screenshots of the terminal.\nfunc randomDir() string {\n\ttmp, err := os.MkdirTemp(os.TempDir(), \"vhs\")\n\tif err != nil {\n\t\tlog.Printf(\"Error creating temporary directory: %v\", err)\n\t}\n\treturn tmp\n}\n\n// VideoOutputs is a mapping from file type to file path for all video outputs\n// of VHS.\ntype VideoOutputs struct {\n\tGIF    string\n\tWebM   string\n\tMP4    string\n\tFrames string\n}\n\n// VideoOptions is the set of options for converting frames to a GIF.\ntype VideoOptions struct {\n\tFramerate     int\n\tPlaybackSpeed float64\n\tInput         string\n\tMaxColors     int\n\tOutput        VideoOutputs\n\tStartingFrame int\n\tStyle         *StyleOptions\n}\n\nconst (\n\tdefaultFramerate     = 50\n\tdefaultStartingFrame = 1\n)\n\n// DefaultVideoOptions is the set of default options for converting frames\n// to a GIF, which are used if they are not overridden.\nfunc DefaultVideoOptions() VideoOptions {\n\treturn VideoOptions{\n\t\tFramerate:     defaultFramerate,\n\t\tInput:         randomDir(),\n\t\tMaxColors:     defaultMaxColors,\n\t\tOutput:        VideoOutputs{GIF: \"\", WebM: \"\", MP4: \"\", Frames: \"\"},\n\t\tPlaybackSpeed: defaultPlaybackSpeed,\n\t\tStartingFrame: defaultStartingFrame,\n\t}\n}\n\nfunc marginFillIsColor(marginFill string) bool {\n\treturn strings.HasPrefix(marginFill, \"#\")\n}\n\n// makeMedia takes a list of images (as frames) and converts them to a GIF/WebM/MP4.\nfunc makeMedia(opts VideoOptions, targetFile string) *exec.Cmd {\n\tif targetFile == \"\" {\n\t\treturn nil\n\t}\n\n\tlog.Println(GrayStyle.Render(\"Creating \" + targetFile + \"...\"))\n\tensureDir(targetFile)\n\n\t//nolint:gosec\n\treturn exec.Command(\n\t\t\"ffmpeg\",\n\t\tbuildFFopts(opts, targetFile)...,\n\t)\n}\n\n// ensureDir ensures that the file path of the output can be created by\n// creating all the necessary nested folders.\nfunc ensureDir(output string) {\n\terr := os.MkdirAll(filepath.Dir(output), 0o750)\n\tif err != nil {\n\t\tfmt.Println(ErrorStyle.Render(\"Unable to create output directory: \"), output)\n\t}\n}\n\n// buildFFopts assembles an ffmpeg command from some VideoOptions.\nfunc buildFFopts(opts VideoOptions, targetFile string) []string {\n\tvar args []string //nolint:prealloc\n\tstreamCounter := 2\n\n\tstreamBuilder := NewStreamBuilder(streamCounter, opts.Input, opts.Style)\n\n\t// Input frame options, used no matter what\n\t// Stream 0: text frames\n\t// Stream 1: cursor frames\n\tstreamBuilder.args = append(streamBuilder.args,\n\t\t\"-y\",\n\t\t\"-r\", fmt.Sprint(opts.Framerate),\n\t\t\"-start_number\", fmt.Sprint(opts.StartingFrame),\n\t\t\"-i\", filepath.Join(opts.Input, textFrameFormat),\n\t\t\"-r\", fmt.Sprint(opts.Framerate),\n\t\t\"-start_number\", fmt.Sprint(opts.StartingFrame),\n\t\t\"-i\", filepath.Join(opts.Input, cursorFrameFormat),\n\t)\n\n\tstreamBuilder = streamBuilder.\n\t\tWithMargin().\n\t\tWithBar().\n\t\tWithCorner()\n\n\tfilterBuilder := NewVideoFilterBuilder(&opts).\n\t\tWithWindowBar(streamBuilder.barStream).\n\t\tWithBorderRadius(streamBuilder.cornerStream).\n\t\tWithMarginFill(streamBuilder.marginStream)\n\n\t// Format-specific options\n\tswitch filepath.Ext(targetFile) {\n\tcase gif:\n\t\tfilterBuilder = filterBuilder.WithGIF()\n\tcase webm:\n\t\tstreamBuilder = streamBuilder.WithWebm()\n\tcase mp4:\n\t\tstreamBuilder = streamBuilder.WithMP4()\n\t}\n\n\targs = append(args, streamBuilder.Build()...)\n\targs = append(args, filterBuilder.Build()...)\n\targs = append(args, targetFile)\n\n\treturn args\n}\n\n// MakeGIF takes a list of images (as frames) and converts them to a GIF.\nfunc MakeGIF(opts VideoOptions) *exec.Cmd {\n\treturn makeMedia(opts, opts.Output.GIF)\n}\n\n// MakeWebM takes a list of images (as frames) and converts them to a WebM.\nfunc MakeWebM(opts VideoOptions) *exec.Cmd {\n\treturn makeMedia(opts, opts.Output.WebM)\n}\n\n// MakeMP4 takes a list of images (as frames) and converts them to an MP4.\nfunc MakeMP4(opts VideoOptions) *exec.Cmd {\n\treturn makeMedia(opts, opts.Output.MP4)\n}\n"
  }
]