├── .editorconfig ├── .github └── workflows │ ├── build.yml │ ├── palette.yml │ └── release-plz.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── ferris.webp ├── simple-example.png ├── simple-example.webp ├── term-example.png └── term-example.webp ├── build.rs ├── examples ├── css.rs ├── custom_flavor.rs ├── ratatui.rs ├── serde.rs ├── simple.rs └── term_grid.rs ├── renovate.json └── src ├── lib.rs └── palette.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # EditorConfig is awesome: https://EditorConfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | indent_size = 2 10 | indent_style = space 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | # go 16 | [*.go] 17 | indent_style = tab 18 | indent_size = 4 19 | 20 | # python 21 | [*.{ini,py,py.tpl,rst}] 22 | indent_size = 4 23 | 24 | # rust 25 | [*.rs] 26 | indent_size = 4 27 | 28 | # documentation, utils 29 | [*.{md,mdx,diff}] 30 | trim_trailing_whitespace = false 31 | 32 | # windows shell scripts 33 | [*.{cmd,bat,ps1}] 34 | end_of_line = crlf 35 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | paths: 7 | - "src/**" 8 | - "examples/**" 9 | - "build.rs" 10 | - "Cargo.toml" 11 | pull_request: 12 | paths: 13 | - "src/**" 14 | - "examples/**" 15 | - "build.rs" 16 | - "Cargo.toml" 17 | 18 | jobs: 19 | compile: 20 | runs-on: ubuntu-24.04 21 | env: 22 | RUST_BACKTRACE: 1 23 | steps: 24 | - uses: actions/checkout@v4 25 | - uses: dtolnay/rust-toolchain@master 26 | with: 27 | toolchain: stable 28 | - uses: Swatinem/rust-cache@v2 29 | - run: cargo build --all-features --verbose 30 | - run: cargo test --all-features --verbose 31 | 32 | rustfmt: 33 | name: rustfmt 34 | runs-on: ubuntu-24.04 35 | steps: 36 | - uses: actions/checkout@v4 37 | - uses: dtolnay/rust-toolchain@master 38 | with: 39 | toolchain: stable 40 | components: rustfmt 41 | - run: cargo fmt --all --check 42 | -------------------------------------------------------------------------------- /.github/workflows/palette.yml: -------------------------------------------------------------------------------- 1 | name: Palette 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | workflow_dispatch: 8 | schedule: 9 | - cron: '0 0 * * *' # Run every day at midnight UTC 10 | 11 | jobs: 12 | createPullRequest: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Make changes to pull request 18 | run: curl -Lo src/palette.json 'https://raw.githubusercontent.com/catppuccin/palette/main/palette.json' 19 | 20 | - name: Create Pull Request 21 | id: cpr 22 | uses: peter-evans/create-pull-request@v7 23 | with: 24 | commit-message: 'feat: auto-sync upstream palettes' 25 | committer: GitHub 26 | author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> 27 | signoff: false 28 | branch: new-palettes 29 | delete-branch: true 30 | title: 'feat: auto-sync upstream palettes' 31 | body: | 32 | Auto-update `src/palette.json` based on https://github.com/catppuccin/palette/blob/main/palette.json 33 | -------------------------------------------------------------------------------- /.github/workflows/release-plz.yml: -------------------------------------------------------------------------------- 1 | name: Release-plz 2 | 3 | permissions: 4 | pull-requests: write 5 | contents: write 6 | 7 | on: 8 | push: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | # Release unpublished packages. 14 | release-plz-release: 15 | name: Release-plz release 16 | runs-on: ubuntu-latest 17 | permissions: 18 | contents: write 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | - name: Install Rust toolchain 25 | uses: dtolnay/rust-toolchain@stable 26 | - name: Run release-plz 27 | uses: release-plz/action@v0.5 28 | with: 29 | command: release 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 33 | 34 | # Create a PR with the new versions and changelog, preparing the next release. 35 | release-plz-pr: 36 | name: Release-plz PR 37 | runs-on: ubuntu-latest 38 | permissions: 39 | contents: write 40 | pull-requests: write 41 | concurrency: 42 | group: release-plz-${{ github.ref }} 43 | cancel-in-progress: false 44 | steps: 45 | - name: Checkout repository 46 | uses: actions/checkout@v4 47 | with: 48 | fetch-depth: 0 49 | - name: Install Rust toolchain 50 | uses: dtolnay/rust-toolchain@stable 51 | - name: Run release-plz 52 | uses: release-plz/action@v0.5 53 | with: 54 | command: release-pr 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | Cargo.lock 3 | target/ 4 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.5.0 4 | hooks: 5 | - id: check-added-large-files 6 | - id: end-of-file-fixer 7 | - id: trailing-whitespace 8 | - repo: https://github.com/doublify/pre-commit-rust 9 | rev: v1.0 10 | hooks: 11 | - id: cargo-check 12 | - id: clippy 13 | - id: fmt 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [2.5.1](https://github.com/catppuccin/rust/compare/v2.5.0...v2.5.1) - 2025-02-23 11 | 12 | ### Fixed 13 | 14 | - use correct colours in ansi colour pairs (#45) 15 | 16 | ## [2.5.0](https://github.com/catppuccin/rust/compare/v2.5.0-beta.0...v2.5.0) - 2025-02-20 17 | 18 | ### Other 19 | 20 | - add changelog 21 | - replace publish workflow with release-plz 22 | - *(deps)* update rust crate itertools to 0.14.0 (#42) 23 | 24 | ### Changed 25 | 26 | - Replace publish workflow with release-plz 27 | - Update rust crate itertools to 0.14.0 (#42) 28 | 29 | ## [2.5.0-beta.0] - 2024-12-07 30 | 31 | ### Added 32 | 33 | - Add ANSI colours (#38) 34 | 35 | ### Changed 36 | 37 | - Bump version number 38 | - Update dependency ubuntu to v24 (#34) 39 | - Update peter-evans/create-pull-request action to v7 (#32) 40 | - Upgrade dependencies (#41) 41 | - Only run on `main` branch (#37) 42 | - Replace code strings with tokenstreams (#29) 43 | 44 | ## [2.4.0] - 2024-05-23 45 | 46 | ### Changed 47 | 48 | - Bump version number 49 | - Update peter-evans/create-pull-request action to v6 (#28) 50 | - Update actions/checkout action to v4 (#27) 51 | - Update rust crate itertools to 0.13.0 (#24) 52 | - Expose `order` for flavors and colors (#22) 53 | - Configure Renovate (#23) 54 | 55 | ### Fixed 56 | 57 | - Update rust crate ratatui to 0.26 (#25) 58 | 59 | ## [2.3.0] - 2024-05-23 60 | 61 | ### Added 62 | 63 | - Add support for emojis (#21) 64 | 65 | ### Changed 66 | 67 | - Bump version number 68 | - Auto-sync upstream palettes (#19) 69 | 70 | ## [2.2.0] - 2024-03-18 71 | 72 | ### Added 73 | 74 | - Add const equivalents of color & flavor index impls (#18) 75 | 76 | ### Changed 77 | 78 | - Bump version number 79 | - Ignore tags in palette workflow (#17) 80 | 81 | ## [2.1.1] - 2024-03-17 82 | 83 | ### Added 84 | 85 | - Add homepage & docs links to cargo manifest 86 | 87 | ## [2.1.0] - 2024-03-10 88 | 89 | ### Added 90 | 91 | - Add FromStr & deserialization support (#16) 92 | 93 | ### Changed 94 | 95 | - Bump version number 96 | 97 | ## [2.0.0] - 2024-03-05 98 | 99 | ### Changed 100 | 101 | - Rewrite with codegen and simpler api (#15) 102 | 103 | ## [1.4.0] - 2024-02-07 104 | 105 | ### Added 106 | 107 | - Add conversion to ratatui Color (#9) 108 | 109 | ### Changed 110 | 111 | - Bump version number 112 | - Make colors/flavors accessible in const context (#10) 113 | 114 | ## [1.3.0] - 2023-07-31 115 | 116 | ### Added 117 | 118 | - Add method to convert a FlavourColours into a fields iterator 119 | 120 | ### Changed 121 | 122 | - Make sure we build before publish 123 | 124 | ## [1.2.2] - 2023-07-30 125 | 126 | ### Added 127 | 128 | - Add `build.yml` & add `publish.yml` 129 | - Add .editorconfig 130 | - Add webp rust example assets 131 | - Add rust crate 132 | 133 | ### Changed 134 | 135 | - Bump version 136 | - Make Colour fields public so that custom colors can be used 137 | - Bump version number 138 | - Re-export css_colors when css feature is enabled 139 | - Bump version number 140 | - Integrate with css-colors create 141 | - Update version number in usage docs 142 | - Ignore Cargo.lock 143 | - Bump version number 144 | - Update readme to match template repo 145 | - Add methods to `Flavour` to get each colour (#32) 146 | - Fix tests after changing `into_iter` 147 | - Fix capitalisation of Catppuccin in docs 148 | - Impl `IntoIterator` for `FlavourColours` 149 | - Rename `Palette` to `FlavourColours` 150 | - Rename and relocate iter methods 151 | - Move flavours into enum 152 | - Bump crate version number 153 | - Use crate version in doc comment, add example outputs 154 | 155 | ### Fixed 156 | 157 | - Fix links 158 | - Broken repo link in rust crate 159 | 160 | [unreleased]: https://github.com/catppuccin/rust/compare/v2.5.0-beta.0..HEAD 161 | [2.5.0-beta.0]: https://github.com/catppuccin/rust/compare/v2.4.0..v2.5.0-beta.0 162 | [2.4.0]: https://github.com/catppuccin/rust/compare/v2.3.0..v2.4.0 163 | [2.3.0]: https://github.com/catppuccin/rust/compare/v2.2.0..v2.3.0 164 | [2.2.0]: https://github.com/catppuccin/rust/compare/v2.1.1..v2.2.0 165 | [2.1.1]: https://github.com/catppuccin/rust/compare/v2.1.0..v2.1.1 166 | [2.1.0]: https://github.com/catppuccin/rust/compare/v2.0.0..v2.1.0 167 | [2.0.0]: https://github.com/catppuccin/rust/compare/v1.4.0..v2.0.0 168 | [1.4.0]: https://github.com/catppuccin/rust/compare/v1.3.0..v1.4.0 169 | [1.3.0]: https://github.com/catppuccin/rust/compare/v1.2.2..v1.3.0 170 | 171 | 172 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "catppuccin" 3 | version = "2.5.1" 4 | authors = ["Catppuccin Org "] 5 | edition = "2021" 6 | description = "🦀 Soothing pastel theme for Rust." 7 | documentation = "https://docs.rs/catppuccin" 8 | homepage = "https://github.com/catppuccin/rust" 9 | repository = "https://github.com/catppuccin/rust" 10 | license = "MIT" 11 | keywords = ["catppuccin", "palette", "color", "colorscheme", "theme"] 12 | 13 | [package.metadata.docs.rs] 14 | all-features = true 15 | 16 | [lints] 17 | rust.missing_docs = "warn" 18 | clippy.all = "warn" 19 | clippy.pedantic = "warn" 20 | clippy.nursery = "warn" 21 | 22 | [dependencies] 23 | ansi_term = { version = "0.12.1", optional = true } 24 | css-colors = { version = "1.0.1", optional = true } 25 | ratatui = { version = "0.29.0", optional = true } 26 | serde = { version = "1.0.203", features = ["derive"], optional = true } 27 | 28 | [build-dependencies] 29 | itertools = "0.14.0" 30 | prettyplease = "0.2.20" 31 | proc-macro2 = "1.0.84" 32 | quote = "1.0.36" 33 | serde = { version = "1.0.203", features = ["derive"] } 34 | serde_json = "1.0.117" 35 | syn = "2.0.66" 36 | 37 | [dev-dependencies] 38 | crossterm = "0.28.1" 39 | serde_json = "1.0.117" 40 | 41 | [features] 42 | ansi-term = ["dep:ansi_term"] 43 | css-colors = ["dep:css-colors"] 44 | ratatui = ["dep:ratatui"] 45 | serde = ["dep:serde"] 46 | 47 | [[example]] 48 | name = "css" 49 | required-features = ["css-colors"] 50 | 51 | [[example]] 52 | name = "term_grid" 53 | required-features = ["ansi-term"] 54 | 55 | [[example]] 56 | name = "ratatui" 57 | required-features = ["ratatui"] 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Catppuccin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Logo
3 | 4 | Catppuccin for Rust 5 | 6 |

7 | 8 |

9 | 10 | 11 | 12 |

13 | 14 |

15 | 16 |

17 | 18 | ## Usage 19 | 20 | Add Catppuccin to your project's `Cargo.toml`: 21 | 22 | ```console 23 | $ cargo add catppuccin 24 | ``` 25 | 26 | ## Example 27 | 28 | ```rust 29 | struct Button { 30 | text: String, 31 | background_color: String, 32 | }; 33 | 34 | fn confirm(text: String) -> Button { 35 | Button { 36 | text, 37 | background_color: catppuccin::PALETTE.mocha.colors.green.hex.to_string(), 38 | } 39 | } 40 | ``` 41 | 42 | More examples can be found 43 | [here](https://github.com/catppuccin/rust/tree/main/examples). 44 | 45 | ## Optional Features 46 | 47 | ### ANSI string painting 48 | 49 | Enable the `ansi-term` feature to add the 50 | `Color::ansi_paint` method. 51 | This adds [ansi-term](https://crates.io/crates/ansi_term) as a dependency. 52 | 53 | Example: [`examples/term_grid.rs`](https://github.com/catppuccin/rust/blob/main/examples/term_grid.rs) 54 | 55 | #### CSS colors 56 | 57 | Enable the `css-colors` feature to enable the conversion of Catppuccin colors to 58 | `css_colors::RGB` instances. 59 | This adds [css-colors](https://crates.io/crates/css-colors) as a dependency. 60 | 61 | Example: [`examples/css.rs`](https://github.com/catppuccin/rust/blob/main/examples/css.rs) 62 | 63 | #### Ratatui 64 | 65 | Enable the `ratatui` feature to enable the conversion of Catppuccin colors to 66 | `ratatui::style::Color` instances. 67 | This adds [ratatui](https://crates.io/crates/ratatui) as a dependency. 68 | 69 | Example: [`examples/ratatui.rs`](https://github.com/catppuccin/rust/blob/main/examples/ratatui.rs) 70 | 71 | #### Serde 72 | 73 | Enable the `serde` feature to enable the serialization of Catppuccin's palette, 74 | flavor, and color types. 75 | This adds [serde](https://crates.io/crates/serde) as a dependency. 76 | 77 | Example: [`examples/serde.rs`](https://github.com/catppuccin/rust/blob/main/examples/serde.rs) 78 | 79 | ## Contributing 80 | 81 | This project uses [pre-commit](https://pre-commit.com/) to maintain consistent code style and standards. 82 | 83 | See also [CONTRIBUTING.md](https://github.com/catppuccin/catppuccin/blob/main/CONTRIBUTING.md) 84 | 85 | ## 💝 Thanks to 86 | 87 | - [backwardspy](https://github.com/backwardspy) 88 | - [Gingeh](https://github.com/Gingeh) 89 | - [Julius](https://github.com/juliuskreutz) 90 | - [Nyx](https://github.com/nyxkrage) 91 | 92 |   93 | 94 |

95 | 96 |

97 | 98 |

99 | Copyright © 2021-present Catppuccin Org 100 |

101 | 102 |

103 | 104 |

105 | -------------------------------------------------------------------------------- /assets/ferris.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catppuccin/rust/59db81af28ed8418a4f93b711d8143a7eac60a36/assets/ferris.webp -------------------------------------------------------------------------------- /assets/simple-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catppuccin/rust/59db81af28ed8418a4f93b711d8143a7eac60a36/assets/simple-example.png -------------------------------------------------------------------------------- /assets/simple-example.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catppuccin/rust/59db81af28ed8418a4f93b711d8143a7eac60a36/assets/simple-example.webp -------------------------------------------------------------------------------- /assets/term-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catppuccin/rust/59db81af28ed8418a4f93b711d8143a7eac60a36/assets/term-example.png -------------------------------------------------------------------------------- /assets/term-example.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catppuccin/rust/59db81af28ed8418a4f93b711d8143a7eac60a36/assets/term-example.webp -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | //! Build script for the Catppuccin crate. 2 | //! This script uses the palette JSON file from the catppuccin/palette github repo 3 | //! in order to populate the `FlavorColors` struct as well as implement the various 4 | //! iteration & indexing primitives offered by the crate. 5 | use std::{ 6 | collections::HashMap, 7 | env, 8 | error::Error, 9 | fs::File, 10 | io::{BufReader, BufWriter, Write}, 11 | path::PathBuf, 12 | }; 13 | 14 | use itertools::Itertools; 15 | use proc_macro2::TokenStream; 16 | use quote::{format_ident, quote}; 17 | use serde::Deserialize; 18 | 19 | #[derive(Debug, Deserialize)] 20 | struct Palette { 21 | #[allow(dead_code)] 22 | version: String, 23 | #[serde(flatten)] 24 | flavors: HashMap, 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | struct Flavor { 29 | emoji: char, 30 | order: u32, 31 | dark: bool, 32 | colors: HashMap, 33 | #[serde(rename = "ansiColors")] 34 | ansi_colors: HashMap, 35 | } 36 | 37 | #[derive(Debug, Deserialize)] 38 | struct Color { 39 | name: String, 40 | order: u32, 41 | rgb: Rgb, 42 | hsl: Hsl, 43 | accent: bool, 44 | } 45 | 46 | #[derive(Debug, Deserialize)] 47 | struct Rgb { 48 | r: u8, 49 | g: u8, 50 | b: u8, 51 | } 52 | 53 | #[derive(Debug, Deserialize)] 54 | struct Hsl { 55 | h: f64, 56 | s: f64, 57 | l: f64, 58 | } 59 | 60 | #[derive(Debug, Deserialize)] 61 | struct AnsiColorPair { 62 | name: String, 63 | order: u32, 64 | normal: AnsiColor, 65 | bright: AnsiColor, 66 | } 67 | 68 | #[derive(Debug, Deserialize)] 69 | struct AnsiColor { 70 | name: String, 71 | rgb: Rgb, 72 | hsl: Hsl, 73 | code: u8, 74 | } 75 | 76 | fn main() -> Result<(), Box> { 77 | let out_dir = PathBuf::from(&env::var("OUT_DIR")?); 78 | let codegen_path = out_dir.join("generated_palette.rs"); 79 | let mut code_writer = BufWriter::new(File::create(codegen_path)?); 80 | 81 | let palette: Palette = 82 | serde_json::from_reader(BufReader::new(File::open("src/palette.json")?))?; 83 | let sample_flavor = palette 84 | .flavors 85 | .values() 86 | .next() 87 | .expect("at least one flavor"); 88 | 89 | let flavor_tokens = [ 90 | // Colors 91 | make_flavor_colors_struct_tokens(sample_flavor), 92 | make_flavor_colors_all_impl_tokens(sample_flavor), 93 | // ANSI Colors 94 | make_flavor_ansi_colors_struct_tokens(sample_flavor), 95 | make_flavor_ansi_colors_all_impl_tokens(sample_flavor), 96 | // ANSI Color Pairs 97 | make_flavor_ansi_color_pairs_struct_tokens(sample_flavor), 98 | make_flavor_ansi_color_pairs_all_impl_tokens(sample_flavor), 99 | ]; 100 | let color_tokens = [ 101 | make_color_name_enum_tokens(sample_flavor), 102 | make_color_name_index_impl_tokens(sample_flavor), 103 | make_color_name_display_impl_tokens(sample_flavor), 104 | make_color_name_identifier_impl_tokens(sample_flavor), 105 | make_color_name_fromstr_impl_tokens(sample_flavor), 106 | ]; 107 | let ansi_color_tokens = [ 108 | make_ansi_color_name_enum_tokens(sample_flavor), 109 | make_ansi_color_name_index_impl_tokens(sample_flavor), 110 | make_ansi_color_name_display_impl_tokens(sample_flavor), 111 | make_ansi_color_name_identifier_impl_tokens(sample_flavor), 112 | make_ansi_color_name_fromstr_impl_tokens(sample_flavor), 113 | ]; 114 | let ansi_color_pair_tokens = [ 115 | make_ansi_color_pair_name_enum_tokens(sample_flavor), 116 | make_ansi_color_pair_name_index_impl_tokens(sample_flavor), 117 | make_ansi_color_pair_name_display_impl_tokens(sample_flavor), 118 | make_ansi_color_pair_name_identifier_impl_tokens(sample_flavor), 119 | make_ansi_color_pair_name_fromstr_impl_tokens(sample_flavor), 120 | ]; 121 | let palette_tokens = [make_palette_const_tokens(&palette)]; 122 | 123 | let ast = syn::parse2( 124 | [ 125 | &flavor_tokens[..], 126 | &color_tokens[..], 127 | &ansi_color_tokens[..], 128 | &ansi_color_pair_tokens[..], 129 | &palette_tokens[..], 130 | ] 131 | .concat() 132 | .into_iter() 133 | .collect(), 134 | )?; 135 | let code = prettyplease::unparse(&ast); 136 | write!(&mut code_writer, "{code}")?; 137 | 138 | Ok(()) 139 | } 140 | 141 | fn palette_circle(filename: &str) -> String { 142 | format!( 143 | r#""# 144 | ) 145 | } 146 | 147 | fn color_palette_circles(color_key: &str) -> String { 148 | ["latte", "frappe", "macchiato", "mocha"] 149 | .map(|n| palette_circle(format!("{n}_{color_key}").as_str())) 150 | .into_iter() 151 | .collect::() 152 | } 153 | 154 | fn ansi_color_palette_circles(color_key: &str) -> String { 155 | ["latte", "frappe", "macchiato", "mocha"] 156 | .map(|n| palette_circle(format!("ansi/{n}_ansi_{color_key}").as_str())) 157 | .into_iter() 158 | .collect::() 159 | } 160 | 161 | fn titlecase>(s: S) -> String { 162 | let mut chars = s.as_ref().chars(); 163 | chars.next().map_or_else(String::new, |first| { 164 | first.to_uppercase().to_string() + chars.as_str() 165 | }) 166 | } 167 | 168 | fn remove_whitespace(s: &str) -> String { 169 | s.replace(' ', "") 170 | } 171 | 172 | fn flavors_in_order(palette: &Palette) -> std::vec::IntoIter<(&String, &Flavor)> { 173 | palette 174 | .flavors 175 | .iter() 176 | .sorted_by(|(_, a), (_, b)| a.order.cmp(&b.order)) 177 | } 178 | 179 | fn colors_in_order(flavor: &Flavor) -> std::vec::IntoIter<(&String, &Color)> { 180 | flavor 181 | .colors 182 | .iter() 183 | .sorted_by(|(_, a), (_, b)| a.order.cmp(&b.order)) 184 | } 185 | 186 | fn ansi_color_pairs_in_order( 187 | flavor: &Flavor, 188 | ) -> std::vec::IntoIter<(&String, &AnsiColorPair, String, String)> { 189 | flavor 190 | .ansi_colors 191 | .iter() 192 | .map(|(ident, pair)| { 193 | ( 194 | ident, 195 | pair, 196 | pair.normal.name.to_lowercase().replace(' ', "_"), 197 | pair.bright.name.to_lowercase().replace(' ', "_"), 198 | ) 199 | }) 200 | .sorted_by(|(_, a, _, _), (_, b, _, _)| a.order.cmp(&b.order)) 201 | } 202 | 203 | fn ansi_colors_in_order(flavor: &Flavor) -> std::vec::IntoIter<(String, &AnsiColor)> { 204 | flavor 205 | .ansi_colors 206 | .iter() 207 | .flat_map(|(_, c)| [&c.normal, &c.bright]) 208 | .map(|c| (c.name.to_lowercase().replace(' ', "_"), c)) 209 | .sorted_by(|(_, a), (_, b)| a.code.cmp(&b.code)) 210 | } 211 | 212 | fn make_flavor_colors_struct_tokens(sample_flavor: &Flavor) -> TokenStream { 213 | let colors = colors_in_order(sample_flavor).map(|(k, _)| { 214 | let ident = format_ident!("{k}"); 215 | let color_img = format!(" {}", color_palette_circles(k)); 216 | quote! { 217 | #[doc = #color_img] 218 | pub #ident: Color 219 | } 220 | }); 221 | quote! { 222 | /// All of the colors for a particular flavor of Catppuccin. 223 | /// Obtained via [`Flavor::colors`]. 224 | #[derive(Clone, Copy, Debug, PartialEq)] 225 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 226 | pub struct FlavorColors { 227 | #(#colors),* 228 | } 229 | } 230 | } 231 | 232 | fn make_flavor_ansi_colors_struct_tokens(sample_flavor: &Flavor) -> TokenStream { 233 | let colors = ansi_colors_in_order(sample_flavor).map(|(k, _)| { 234 | let ident = format_ident!("{k}"); 235 | let color_img = format!(" {}", ansi_color_palette_circles(&k)); 236 | quote! { 237 | #[doc = #color_img] 238 | pub #ident: AnsiColor 239 | } 240 | }); 241 | quote! { 242 | /// All of the ANSI colors for a particular flavor of Catppuccin. 243 | /// Obtained via [`Flavor::ansi_colors`]. 244 | #[derive(Clone, Copy, Debug, PartialEq)] 245 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 246 | pub struct FlavorAnsiColors { 247 | #(#colors),* 248 | } 249 | 250 | /// A single ANSI color. 251 | #[derive(Clone, Copy, Debug, PartialEq)] 252 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 253 | pub struct AnsiColor { 254 | /// The [`AnsiColorName`] for this color. 255 | pub name: AnsiColorName, 256 | /// The color represented as a six-digit hex string with a leading hash (#). 257 | pub hex: Hex, 258 | /// The color represented as individual red, green, and blue channels. 259 | pub rgb: Rgb, 260 | /// The color represented as individual hue, saturation, and lightness channels. 261 | pub hsl: Hsl, 262 | /// The color's ANSI code. 263 | pub code: u8, 264 | } 265 | } 266 | } 267 | 268 | fn make_flavor_ansi_color_pairs_struct_tokens(sample_flavor: &Flavor) -> TokenStream { 269 | let color_pairs = ansi_color_pairs_in_order(sample_flavor).map(|(k, ..)| { 270 | let ident = format_ident!("{k}"); 271 | let doc = format!("The normal and bright {k} ANSI color pair."); 272 | quote! { 273 | #[doc = #doc] 274 | pub #ident: AnsiColorPair 275 | } 276 | }); 277 | quote! { 278 | /// All of the ANSI color pairs for a particular flavor of Catppuccin. 279 | #[derive(Clone, Copy, Debug, PartialEq)] 280 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 281 | pub struct FlavorAnsiColorPairs { 282 | #(#color_pairs),* 283 | } 284 | 285 | /// A pair of ANSI colors - normal and bright. 286 | #[derive(Clone, Copy, Debug, PartialEq)] 287 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 288 | pub struct AnsiColorPair { 289 | /// The [`AnsiColorPairName`] for this color. 290 | pub name: AnsiColorPairName, 291 | /// Order of the ANSI color in the palette spec. 292 | pub order: u32, 293 | /// The normal color. 294 | pub normal: AnsiColor, 295 | /// The bright color. 296 | pub bright: AnsiColor, 297 | } 298 | } 299 | } 300 | 301 | fn make_flavor_colors_all_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 302 | let items = colors_in_order(sample_flavor).map(|(identifier, _)| { 303 | let ident = format_ident!("{identifier}"); 304 | quote! { &self.#ident } 305 | }); 306 | quote! { 307 | impl FlavorColors { 308 | /// Get an array of the colors in the flavor. 309 | #[must_use] 310 | pub const fn all_colors(&self) -> [&Color; 26] { 311 | [ 312 | #(#items),* 313 | ] 314 | } 315 | } 316 | } 317 | } 318 | 319 | fn make_flavor_ansi_colors_all_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 320 | let ansi_colors = ansi_colors_in_order(sample_flavor).map(|(identifier, _)| { 321 | let ident = format_ident!("{identifier}"); 322 | quote! { &self.#ident } 323 | }); 324 | let ansi_color_pairs = ansi_color_pairs_in_order(sample_flavor).map( 325 | |(identifier, color_pair, normal_identifier, bright_identifier)| { 326 | make_ansi_color_pair_entry( 327 | identifier, 328 | color_pair, 329 | &normal_identifier, 330 | &bright_identifier, 331 | ) 332 | }, 333 | ); 334 | quote! { 335 | impl FlavorAnsiColors { 336 | /// Get an array of the ANSI colors in the flavor. 337 | #[must_use] 338 | pub const fn all_ansi_colors(&self) -> [&AnsiColor; 16] { 339 | [ 340 | #(#ansi_colors),* 341 | ] 342 | } 343 | 344 | /// Convert the 16 ANSI colors to 8 ANSI color pairs. 345 | #[must_use] 346 | #[allow(clippy::too_many_lines, clippy::unreadable_literal)] 347 | pub const fn to_ansi_color_pairs(&self) -> FlavorAnsiColorPairs { 348 | FlavorAnsiColorPairs { 349 | #(#ansi_color_pairs),* 350 | } 351 | } 352 | } 353 | } 354 | } 355 | 356 | fn make_flavor_ansi_color_pairs_all_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 357 | let items = ansi_color_pairs_in_order(sample_flavor).map(|(identifier, ..)| { 358 | let ident = format_ident!("{identifier}"); 359 | quote! { &self.#ident } 360 | }); 361 | quote! { 362 | impl FlavorAnsiColorPairs { 363 | /// Get an array of the ANSI color pairs in the flavor. 364 | #[must_use] 365 | pub const fn all_ansi_color_pairs(&self) -> [&AnsiColorPair; 8] { 366 | [ 367 | #(#items),* 368 | ] 369 | } 370 | } 371 | } 372 | } 373 | 374 | fn make_color_name_enum_tokens(sample_flavor: &Flavor) -> TokenStream { 375 | let variants = colors_in_order(sample_flavor).map(|(name, _)| { 376 | let ident = format_ident!("{}", titlecase(name)); 377 | let circles = format!(" {}", color_palette_circles(name)); 378 | quote! { 379 | #[doc = #circles] 380 | #ident 381 | } 382 | }); 383 | quote! { 384 | /// Enum of all named Catppuccin colors. Can be used to index into a [`FlavorColors`]. 385 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] 386 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 387 | pub enum ColorName { 388 | #(#variants),* 389 | } 390 | } 391 | } 392 | 393 | fn make_ansi_color_name_enum_tokens(sample_flavor: &Flavor) -> TokenStream { 394 | let variants = ansi_colors_in_order(sample_flavor).map(|(identifier, color)| { 395 | let name = remove_whitespace(&color.name); 396 | let ident = format_ident!("{name}"); 397 | let circles = format!(" {}", ansi_color_palette_circles(&identifier)); 398 | quote! { 399 | #[doc = #circles] 400 | #ident 401 | } 402 | }); 403 | quote! { 404 | /// Enum of all named ANSI colors. Can be used to index into a [`FlavorAnsiColors`] 405 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] 406 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 407 | pub enum AnsiColorName { 408 | #(#variants),* 409 | } 410 | } 411 | } 412 | 413 | fn make_ansi_color_pair_name_enum_tokens(sample_flavor: &Flavor) -> TokenStream { 414 | let variants = ansi_color_pairs_in_order(sample_flavor).map(|(name, ..)| { 415 | let ident = format_ident!("{}", titlecase(name)); 416 | let circles = format!(" {}", ansi_color_palette_circles(name)); 417 | quote! { 418 | #[doc = #circles] 419 | #ident 420 | } 421 | }); 422 | quote! { 423 | /// Enum of all ANSI color pairs. Can be used to index into a [`FlavorAnsiColorPairs`]. 424 | #[derive(Copy, Clone, Eq, PartialEq, Debug)] 425 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 426 | pub enum AnsiColorPairName { 427 | #(#variants),* 428 | } 429 | } 430 | } 431 | 432 | fn make_color_name_index_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 433 | let first = colors_in_order(sample_flavor).map(|(identifier, _)| { 434 | let variant = format_ident!("{}", titlecase(identifier)); 435 | let ident = format_ident!("{}", identifier); 436 | quote! { 437 | ColorName::#variant => &self.#ident 438 | } 439 | }); 440 | let second = first.clone(); 441 | quote! { 442 | impl Index for FlavorColors { 443 | type Output = Color; 444 | 445 | fn index(&self, index: ColorName) -> &Self::Output { 446 | match index { 447 | #(#first),* 448 | } 449 | } 450 | } 451 | 452 | impl FlavorColors { 453 | /// Get a color by name. 454 | /// 455 | /// This is equivalent to using the index operator, but can also be used in 456 | /// const contexts. 457 | #[must_use] 458 | pub const fn get_color(&self, name: ColorName) -> &Color { 459 | match name { 460 | #(#second),* 461 | } 462 | } 463 | } 464 | } 465 | } 466 | 467 | fn make_ansi_color_name_index_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 468 | let first = ansi_colors_in_order(sample_flavor).map(|(identifier, color)| { 469 | let variant = format_ident!("{}", remove_whitespace(&color.name)); 470 | let ident = format_ident!("{}", identifier); 471 | quote! { 472 | AnsiColorName::#variant => &self.#ident 473 | } 474 | }); 475 | let second = first.clone(); 476 | quote! { 477 | impl Index for FlavorAnsiColors { 478 | type Output = AnsiColor; 479 | 480 | fn index(&self, index: AnsiColorName) -> &Self::Output { 481 | match index { 482 | #(#first),* 483 | } 484 | } 485 | } 486 | 487 | impl FlavorAnsiColors { 488 | /// Get an ANSI color by name. 489 | /// 490 | /// This is equivalent to using the index operator, but can also be used in 491 | /// const contexts. 492 | #[must_use] 493 | pub const fn get_ansi_color(&self, name: AnsiColorName) -> &AnsiColor { 494 | match name { 495 | #(#second),* 496 | } 497 | } 498 | } 499 | } 500 | } 501 | 502 | fn make_ansi_color_pair_name_index_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 503 | let first = ansi_color_pairs_in_order(sample_flavor).map(|(identifier, ..)| { 504 | let variant = format_ident!("{}", titlecase(identifier)); 505 | let ident = format_ident!("{}", identifier); 506 | quote! { 507 | AnsiColorPairName::#variant => &self.#ident 508 | } 509 | }); 510 | let second = first.clone(); 511 | quote! { 512 | impl Index for FlavorAnsiColorPairs { 513 | type Output = AnsiColorPair; 514 | 515 | fn index(&self, index: AnsiColorPairName) -> &Self::Output { 516 | match index { 517 | #(#first),* 518 | } 519 | } 520 | } 521 | 522 | impl FlavorAnsiColorPairs { 523 | /// Get an ANSI color pair by name. 524 | /// 525 | /// This is equivalent to using the index operator, but can also be used in 526 | /// const contexts. 527 | #[must_use] 528 | pub const fn get_ansi_color_pair(&self, name: AnsiColorPairName) -> &AnsiColorPair { 529 | match name { 530 | #(#second),* 531 | } 532 | } 533 | } 534 | } 535 | } 536 | 537 | fn make_color_name_display_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 538 | let match_arms = colors_in_order(sample_flavor).map(|(identifier, color)| { 539 | let variant = format_ident!("{}", titlecase(identifier)); 540 | let name = &color.name; 541 | quote! { 542 | Self::#variant => write!(f, #name) 543 | } 544 | }); 545 | quote! { 546 | impl std::fmt::Display for ColorName { 547 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 548 | match self { 549 | #(#match_arms),* 550 | } 551 | } 552 | } 553 | } 554 | } 555 | 556 | fn make_ansi_color_name_display_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 557 | let match_arms = ansi_colors_in_order(sample_flavor).map(|(_, color)| { 558 | let name = &color.name; 559 | let variant = format_ident!("{}", remove_whitespace(name)); 560 | quote! { 561 | Self::#variant => write!(f, #name) 562 | } 563 | }); 564 | quote! { 565 | impl std::fmt::Display for AnsiColorName { 566 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 567 | match self { 568 | #(#match_arms),* 569 | } 570 | } 571 | } 572 | } 573 | } 574 | 575 | fn make_ansi_color_pair_name_display_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 576 | let match_arms = ansi_color_pairs_in_order(sample_flavor).map(|(identifier, ..)| { 577 | let name = titlecase(identifier); 578 | let variant = format_ident!("{name}"); 579 | quote! { 580 | Self::#variant => write!(f, #name) 581 | } 582 | }); 583 | quote! { 584 | impl std::fmt::Display for AnsiColorPairName { 585 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 586 | match self { 587 | #(#match_arms),* 588 | } 589 | } 590 | } 591 | } 592 | } 593 | 594 | fn make_color_name_identifier_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 595 | let match_arms = colors_in_order(sample_flavor).map(|(identifier, _)| { 596 | let variant = format_ident!("{}", titlecase(identifier)); 597 | quote! { 598 | Self::#variant => #identifier 599 | } 600 | }); 601 | quote! { 602 | impl ColorName { 603 | /// Get the color's identifier; the lowercase key used to identify the color. 604 | /// This differs from `to_string` in that it's intended for machine usage 605 | /// rather than presentation. 606 | /// 607 | /// Example: 608 | /// 609 | /// ```rust 610 | /// let surface0 = catppuccin::PALETTE.latte.colors.surface0; 611 | /// assert_eq!(surface0.name.to_string(), "Surface 0"); 612 | /// assert_eq!(surface0.name.identifier(), "surface0"); 613 | /// ``` 614 | #[must_use] 615 | pub const fn identifier(&self) -> &'static str { 616 | match self { 617 | #(#match_arms),* 618 | } 619 | } 620 | } 621 | } 622 | } 623 | 624 | fn make_ansi_color_name_identifier_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 625 | let match_arms = ansi_colors_in_order(sample_flavor).map(|(identifier, color)| { 626 | let variant = format_ident!("{}", remove_whitespace(&color.name)); 627 | quote! { 628 | Self::#variant => #identifier 629 | } 630 | }); 631 | quote! { 632 | impl AnsiColorName { 633 | /// Get the ANSI color's identifier; the lowercase key used to identify the color. 634 | /// This differs from `to_string` in that it's intended for machine usage 635 | /// rather than presentation. 636 | /// 637 | /// Example: 638 | /// 639 | /// ```rust 640 | /// let bright_black = catppuccin::PALETTE.latte.ansi_colors.bright_black; 641 | /// assert_eq!(bright_black.name.to_string(), "Bright Black"); 642 | /// assert_eq!(bright_black.name.identifier(), "bright_black"); 643 | /// ``` 644 | #[must_use] 645 | pub const fn identifier(&self) -> &'static str { 646 | match self { 647 | #(#match_arms),* 648 | } 649 | } 650 | } 651 | } 652 | } 653 | 654 | fn make_ansi_color_pair_name_identifier_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 655 | let match_arms = ansi_color_pairs_in_order(sample_flavor).map(|(identifier, ..)| { 656 | let variant = format_ident!("{}", titlecase(identifier)); 657 | quote! { 658 | Self::#variant => #identifier 659 | } 660 | }); 661 | quote! { 662 | impl AnsiColorPairName { 663 | /// Get the ANSI color pair's identifier; the lowercase key used to identify the color. 664 | /// This differs from `to_string` in that it's intended for machine usage 665 | /// rather than presentation. 666 | /// 667 | /// Example: 668 | /// 669 | /// ```rust 670 | /// let black_ansi_pair = catppuccin::PALETTE.latte.ansi_colors.all_pairs().black; 671 | /// assert_eq!(black_ansi_pair.name.to_string(), "Black"); 672 | /// assert_eq!(black_ansi_pair.name.identifier(), "black"); 673 | /// assert_eq!(black_ansi_pair.normal.name.to_string(), "Black"); 674 | /// assert_eq!(black_ansi_pair.normal.name.identifier(), "black"); 675 | /// assert_eq!(black_ansi_pair.bright.name.to_string(), "Bright Black"); 676 | /// assert_eq!(black_ansi_pair.bright.name.identifier(), "bright_black"); 677 | /// ``` 678 | #[must_use] 679 | pub const fn identifier(&self) -> &'static str { 680 | match self { 681 | #(#match_arms),* 682 | } 683 | } 684 | } 685 | } 686 | } 687 | 688 | fn make_color_name_fromstr_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 689 | let match_arms = colors_in_order(sample_flavor) 690 | .map(|(identifier, _)| { 691 | let variant = format_ident!("{}", titlecase(identifier)); 692 | quote! { 693 | #identifier => Ok(Self::#variant) 694 | } 695 | }) 696 | .collect::>(); 697 | quote! { 698 | impl std::str::FromStr for ColorName { 699 | type Err = ParseColorNameError; 700 | 701 | fn from_str(s: &str) -> Result { 702 | match s { 703 | #(#match_arms),*, 704 | _ => Err(ParseColorNameError), 705 | } 706 | } 707 | } 708 | } 709 | } 710 | 711 | fn make_ansi_color_name_fromstr_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 712 | let match_arms = ansi_colors_in_order(sample_flavor) 713 | .map(|(identifier, color)| { 714 | let variant = format_ident!("{}", remove_whitespace(&color.name)); 715 | quote! { 716 | #identifier => Ok(Self::#variant) 717 | } 718 | }) 719 | .collect::>(); 720 | quote! { 721 | impl std::str::FromStr for AnsiColorName { 722 | type Err = ParseColorNameError; 723 | 724 | fn from_str(s: &str) -> Result { 725 | match s { 726 | #(#match_arms),*, 727 | _ => Err(ParseColorNameError), 728 | } 729 | } 730 | } 731 | } 732 | } 733 | 734 | fn make_ansi_color_pair_name_fromstr_impl_tokens(sample_flavor: &Flavor) -> TokenStream { 735 | let match_arms = ansi_color_pairs_in_order(sample_flavor) 736 | .map(|(identifier, ..)| { 737 | let variant = format_ident!("{}", titlecase(identifier)); 738 | quote! { 739 | #identifier => Ok(Self::#variant) 740 | } 741 | }) 742 | .collect::>(); 743 | quote! { 744 | impl std::str::FromStr for AnsiColorPairName { 745 | type Err = ParseColorNameError; 746 | 747 | fn from_str(s: &str) -> Result { 748 | match s { 749 | #(#match_arms),*, 750 | _ => Err(ParseColorNameError), 751 | } 752 | } 753 | } 754 | } 755 | } 756 | 757 | fn make_palette_const_tokens(palette: &Palette) -> TokenStream { 758 | let flavors = 759 | flavors_in_order(palette).map(|(identifier, flavor)| make_flavor_entry(identifier, flavor)); 760 | let tokens = quote! { 761 | /// The Catppuccin palette. This constant will generally be your entrypoint 762 | /// into using the crate. 763 | #[allow(clippy::unreadable_literal)] 764 | pub const PALETTE: Palette = Palette { 765 | #(#flavors),* 766 | }; 767 | }; 768 | 769 | tokens 770 | } 771 | 772 | fn make_flavor_entry(identifier: &str, flavor: &Flavor) -> TokenStream { 773 | let Flavor { 774 | emoji, order, dark, .. 775 | } = flavor; 776 | let colors = 777 | colors_in_order(flavor).map(|(identifier, color)| make_color_entry(identifier, color)); 778 | let ansi_colors = ansi_colors_in_order(flavor) 779 | .map(|(identifier, ansi_color_pair)| make_ansi_color_entry(&identifier, ansi_color_pair)); 780 | let flavorname_variant = format_ident!("{}", titlecase(identifier)); 781 | let ident = format_ident!("{}", identifier); 782 | quote! { 783 | #ident: Flavor { 784 | name: FlavorName::#flavorname_variant, 785 | emoji: #emoji, 786 | order: #order, 787 | dark: #dark, 788 | colors: FlavorColors { 789 | #(#colors),* 790 | }, 791 | ansi_colors: FlavorAnsiColors { 792 | #(#ansi_colors),* 793 | } 794 | } 795 | } 796 | } 797 | 798 | fn make_color_entry(identifier: &str, color: &Color) -> TokenStream { 799 | let ident = format_ident!("{}", identifier); 800 | let colorname_variant = format_ident!("{}", titlecase(identifier)); 801 | let Color { 802 | order, 803 | accent, 804 | rgb: Rgb { r, g, b }, 805 | hsl: Hsl { h, s, l }, 806 | .. 807 | } = color; 808 | let rgb = quote! { Rgb { r: #r, g: #g, b: #b } }; 809 | let hsl = quote! { Hsl { h: #h, s: #s, l: #l } }; 810 | quote! { 811 | #ident: Color { 812 | name: ColorName::#colorname_variant, 813 | order: #order, 814 | accent: #accent, 815 | hex: Hex(#rgb), 816 | rgb: #rgb, 817 | hsl: #hsl, 818 | } 819 | } 820 | } 821 | 822 | fn make_ansi_color_entry(identifier: &str, ansi_color: &AnsiColor) -> TokenStream { 823 | let ident = format_ident!("{identifier}"); 824 | let AnsiColor { 825 | name, 826 | code, 827 | rgb: Rgb { r, g, b }, 828 | hsl: Hsl { h, s, l }, 829 | } = ansi_color; 830 | 831 | let name_variant = format_ident!("{}", remove_whitespace(name)); 832 | let rgb = quote! { Rgb { r: #r, g: #g, b: #b } }; 833 | let hsl = quote! { Hsl { h: #h, s: #s, l: #l } }; 834 | 835 | quote! { 836 | #ident: AnsiColor { 837 | name: AnsiColorName::#name_variant, 838 | hex: Hex(#rgb), 839 | rgb: #rgb, 840 | hsl: #hsl, 841 | code: #code, 842 | } 843 | } 844 | } 845 | 846 | fn make_ansi_color_pair_entry( 847 | identifier: &str, 848 | ansi_color_pair: &AnsiColorPair, 849 | normal_identifier: &str, 850 | bright_identifier: &str, 851 | ) -> TokenStream { 852 | let identifier = format_ident!("{}", identifier); 853 | let name_identifier = format_ident!("{}", ansi_color_pair.name); 854 | let order = ansi_color_pair.order; 855 | let normal_identifier = format_ident!("{}", normal_identifier); 856 | let bright_identifier = format_ident!("{}", bright_identifier); 857 | 858 | quote! { 859 | #identifier: AnsiColorPair { 860 | name: AnsiColorPairName::#name_identifier, 861 | order: #order, 862 | normal: self.#normal_identifier, 863 | bright: self.#bright_identifier, 864 | } 865 | } 866 | } 867 | -------------------------------------------------------------------------------- /examples/css.rs: -------------------------------------------------------------------------------- 1 | //! Example demonstrating integration with the `css-colors` crate. 2 | use css_colors::{percent, Color}; 3 | 4 | fn main() { 5 | let teal = catppuccin::PALETTE.mocha.colors.teal; 6 | let rgb: css_colors::RGB = teal.into(); 7 | 8 | println!("RGB: {}", rgb.to_css()); 9 | 10 | let hsl = rgb.to_hsl(); 11 | println!("HSL: {}", hsl.to_css()); 12 | 13 | let lighter = hsl.lighten(percent(20)); 14 | println!("20% lighter: {lighter}"); 15 | 16 | let ansi_normal_magenta = catppuccin::PALETTE.mocha.ansi_colors.magenta; 17 | let ansi_bright_magenta = catppuccin::PALETTE.mocha.ansi_colors.bright_magenta; 18 | let ansi_magenta_normal_rgb: css_colors::RGB = ansi_normal_magenta.into(); 19 | let ansi_magenta_bright_rgb: css_colors::RGB = ansi_bright_magenta.into(); 20 | 21 | println!("ANSI Magenta RGB: {}", ansi_magenta_normal_rgb.to_css()); 22 | println!( 23 | "ANSI Bright Magenta RGB: {}", 24 | ansi_magenta_bright_rgb.to_css() 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /examples/custom_flavor.rs: -------------------------------------------------------------------------------- 1 | //! Example demonstrating how to make a custom flavor. 2 | //! Two options are provided; setting colors one-by-one, or using a helper macro. 3 | use catppuccin::{Color, Flavor, FlavorColors}; 4 | 5 | fn americano_simple() -> Flavor { 6 | let mut oled = catppuccin::PALETTE.mocha; 7 | 8 | oled.colors.base.hex = (0, 0, 0).into(); 9 | oled.colors.base.rgb = (0, 0, 0).into(); 10 | oled.colors.base.hsl = (0.0, 0.0, 0.0).into(); 11 | 12 | oled.colors.mantle.hex = (10, 10, 10).into(); 13 | oled.colors.mantle.rgb = (10, 10, 10).into(); 14 | oled.colors.mantle.hsl = (0.0, 0.0, 0.04).into(); 15 | 16 | oled.colors.crust.hex = (0, 0, 0).into(); 17 | oled.colors.crust.rgb = (0, 0, 0).into(); 18 | oled.colors.crust.hsl = (0.0, 0.0, 0.08).into(); 19 | 20 | oled 21 | } 22 | 23 | macro_rules! custom_flavor { 24 | ($base:expr, $($color_key:ident: $rgb:expr, $hsl:expr,)*) => { 25 | Flavor { 26 | colors: FlavorColors { 27 | $($color_key: Color { 28 | hex: $rgb.into(), 29 | rgb: $rgb.into(), 30 | hsl: $hsl.into(), 31 | ..$base.colors.$color_key 32 | },)* 33 | ..$base.colors 34 | }, 35 | ..$base 36 | } 37 | }; 38 | } 39 | 40 | fn use_flavor(flavor: &Flavor) { 41 | println!("bg: {}", flavor.colors.base.hex); 42 | println!("bg2: {}", flavor.colors.mantle.hex); 43 | println!("fg: {}", flavor.colors.text.hex); 44 | println!("accent: {}", flavor.colors.mauve.hex); 45 | } 46 | 47 | fn main() { 48 | println!("The simple way:"); 49 | let flavor = americano_simple(); 50 | use_flavor(&flavor); 51 | println!(); 52 | 53 | println!("Or with a macro:"); 54 | let flavor = custom_flavor!(catppuccin::PALETTE.mocha, 55 | base: (0, 0, 0), (0.0, 0.0, 0.0), 56 | mantle: (10, 10, 10), (0.0, 0.0, 0.04), 57 | crust: (20, 20, 20), (0.0, 0.0, 0.08), 58 | ); 59 | use_flavor(&flavor); 60 | } 61 | -------------------------------------------------------------------------------- /examples/ratatui.rs: -------------------------------------------------------------------------------- 1 | //! Example demonstrating integration with the `ratatui` crate. 2 | use std::io::{self, stdout}; 3 | 4 | use catppuccin::PALETTE; 5 | use ratatui::{ 6 | backend::CrosstermBackend, 7 | layout::Rect, 8 | style::Stylize as _, 9 | text::{Line, Span}, 10 | widgets::{Paragraph, Widget}, 11 | Terminal, TerminalOptions, Viewport, 12 | }; 13 | 14 | fn main() -> io::Result<()> { 15 | let mut terminal = Terminal::with_options( 16 | CrosstermBackend::new(stdout()), 17 | TerminalOptions { 18 | viewport: Viewport::Inline(0), 19 | }, 20 | )?; 21 | for flavor in &PALETTE { 22 | terminal.insert_before(8, |buf| { 23 | let analogous: Vec = flavor 24 | .colors 25 | .into_iter() 26 | .filter(|c| c.accent) 27 | .map(|c| "██".fg(*c)) // fg accepts any type that implements Into 28 | .collect::>(); 29 | let monochromatic: Vec = flavor 30 | .colors 31 | .into_iter() 32 | .filter(|c| !c.accent) 33 | .map(|c| "██".fg(*c)) // fg accepts any type that implements Into 34 | .collect(); 35 | let ansi_normals: Vec = flavor 36 | .ansi_colors 37 | .into_iter() 38 | .filter(|c| c.code < 8) 39 | .map(|c| "██".fg(*c)) // fg accepts any type that implements Into 40 | .collect::>(); 41 | let ansi_brights: Vec = flavor 42 | .ansi_colors 43 | .into_iter() 44 | .filter(|c| c.code >= 8) 45 | .map(|c| "██".fg(*c)) // fg accepts any type that implements Into 46 | .collect::>(); 47 | 48 | let width = buf.area.width; 49 | Paragraph::new(flavor.name.to_string()).render(Rect::new(0, 0, width, 1), buf); 50 | Paragraph::new(Line::from(analogous)).render(Rect::new(0, 1, width, 1), buf); 51 | Paragraph::new(Line::from(monochromatic)).render(Rect::new(0, 2, width, 1), buf); 52 | Paragraph::new(format!("{} ANSI", flavor.name)).render(Rect::new(0, 4, width, 1), buf); 53 | Paragraph::new(Line::from(ansi_normals)).render(Rect::new(0, 5, width, 1), buf); 54 | Paragraph::new(Line::from(ansi_brights)).render(Rect::new(0, 6, width, 1), buf); 55 | })?; 56 | } 57 | 58 | Ok(()) 59 | } 60 | -------------------------------------------------------------------------------- /examples/serde.rs: -------------------------------------------------------------------------------- 1 | //! Example demonstrating integration with the `serde` crate. 2 | fn main() { 3 | let value = 4 | serde_json::to_string_pretty(&catppuccin::PALETTE).expect("palette can be serialized"); 5 | println!("{value}"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/simple.rs: -------------------------------------------------------------------------------- 1 | //! Simple example showing how to get colors from the Catppuccin palette. 2 | use catppuccin::{AnsiColor, ColorName, Rgb, PALETTE}; 3 | 4 | fn main() { 5 | let latte_teal = PALETTE.latte.colors.teal; 6 | let Rgb { r, g, b } = latte_teal.rgb; 7 | println!( 8 | "Latte's {} is {}, which is rgb({r}, {g}, {b})", 9 | latte_teal.name, latte_teal.hex 10 | ); 11 | 12 | // you can also get a color by its name, from `FlavorColors` or `Flavor`: 13 | let mocha = &PALETTE.mocha; 14 | let mocha_teal = mocha.colors[ColorName::Teal]; 15 | let mocha_mauve = mocha[ColorName::Mauve]; 16 | 17 | let Rgb { r, g, b } = mocha_teal.rgb; 18 | println!( 19 | "Mocha's {} is {}, which is rgb({r}, {g}, {b})", 20 | mocha_teal.name, mocha_teal.hex 21 | ); 22 | 23 | println!("Mocha's {} is {}", mocha_mauve.name, mocha_mauve.hex); 24 | println!(); 25 | 26 | // iterate over the 16 ANSI colors (i.e. Black, Red, ..., Bright Black, Bright Red, ...) 27 | println!("Mocha's ANSI colors in code order:"); 28 | for AnsiColor { 29 | name, 30 | rgb, 31 | hsl, 32 | code, 33 | hex, 34 | } in &mocha.ansi_colors 35 | { 36 | println!( 37 | "Mocha ANSI [{:2}] {:15} → {:6} {:3?} {:19?}", 38 | code, 39 | name.to_string(), 40 | hex, 41 | rgb, 42 | hsl, 43 | ); 44 | } 45 | println!(); 46 | 47 | // iterate over the 16 ANSI colors in 8 pairs (i.e. Black, Bright Black, Red, Bright Red, ...) 48 | println!("Mocha's ANSI color pairs:"); 49 | for pair in &mocha.ansi_colors.all_pairs() { 50 | println!( 51 | "[{:2}] {:7} / [{:2}] {}", 52 | pair.normal.code, 53 | pair.normal.name.to_string(), 54 | pair.bright.code, 55 | pair.bright.name 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/term_grid.rs: -------------------------------------------------------------------------------- 1 | //! Example demonstrating integration with the `ansi_term` crate. 2 | use catppuccin::PALETTE; 3 | 4 | const fn ansi_term_color(color: &catppuccin::Color) -> ansi_term::Colour { 5 | ansi_term::Colour::RGB(color.rgb.r, color.rgb.g, color.rgb.b) 6 | } 7 | const fn ansi_term_ansi_color(color: &catppuccin::AnsiColor) -> ansi_term::Colour { 8 | ansi_term::Colour::RGB(color.rgb.r, color.rgb.g, color.rgb.b) 9 | } 10 | 11 | fn main() { 12 | for flavor in &PALETTE { 13 | let heading = format!( 14 | "{} ({})", 15 | flavor.name, 16 | if flavor.dark { "dark" } else { "light" } 17 | ); 18 | println!( 19 | "{}\n", 20 | ansi_term::Style::new().underline().bold().paint(heading) 21 | ); 22 | 23 | for color in flavor { 24 | let name = format!( 25 | "{}{}", 26 | color.name, 27 | if color.accent { " (accent)" } else { "" } 28 | ); 29 | let rgb = format!( 30 | "rgb({:3}, {:3}, {:3})", 31 | color.rgb.r, color.rgb.g, color.rgb.b 32 | ); 33 | let hsl = format!( 34 | "hsl({:3.0}, {:5.3}, {:5.3})", 35 | color.hsl.h, color.hsl.s, color.hsl.l 36 | ); 37 | println!( 38 | "{} {:18} → {:6} {:18} {:18}", 39 | ansi_term_color(color).reverse().paint(" "), 40 | name, 41 | color.hex, 42 | rgb, 43 | hsl, 44 | ); 45 | } 46 | println!(); 47 | 48 | println!( 49 | "{}\n", 50 | ansi_term::Style::new() 51 | .underline() 52 | .bold() 53 | .paint(format!("{} ANSI", flavor.name)) 54 | ); 55 | 56 | for ansi_color in &flavor.ansi_colors { 57 | let rgb = format!( 58 | "rgb({:3}, {:3}, {:3})", 59 | ansi_color.rgb.r, ansi_color.rgb.g, ansi_color.rgb.b 60 | ); 61 | let hsl = format!( 62 | "hsl({:3.0}, {:5.3}, {:5.3})", 63 | ansi_color.hsl.h, ansi_color.hsl.s, ansi_color.hsl.l 64 | ); 65 | 66 | println!( 67 | "{} {:15} → {:6} {:18} {:18}", 68 | ansi_term_ansi_color(ansi_color).reverse().paint(" "), 69 | ansi_color.name.to_string(), 70 | ansi_color.hex, 71 | rgb, 72 | hsl, 73 | ); 74 | } 75 | println!(); 76 | 77 | println!( 78 | "{}\n", 79 | ansi_term::Style::new() 80 | .underline() 81 | .bold() 82 | .paint(format!("{} ANSI Pairs", flavor.name)) 83 | ); 84 | 85 | for ansi_color_pair in &flavor.ansi_colors.to_ansi_color_pairs() { 86 | println!( 87 | "{}{} {}", 88 | ansi_term_ansi_color(&ansi_color_pair.normal) 89 | .reverse() 90 | .paint(" "), 91 | ansi_term_ansi_color(&ansi_color_pair.bright) 92 | .reverse() 93 | .paint(" "), 94 | ansi_color_pair.name, 95 | ); 96 | } 97 | println!(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! 🦀 Soothing pastel theme for Rust. 2 | //! 3 | //! # Usage 4 | //! 5 | //! Add Catppuccin to your project's `Cargo.toml`: 6 | //! 7 | //! ```console 8 | //! $ cargo add catppuccin 9 | //! ``` 10 | //! 11 | //! # Example 12 | //! 13 | //! ```rust 14 | //! struct Button { 15 | //! text: String, 16 | //! background_color: String, 17 | //! }; 18 | //! 19 | //! fn confirm(text: String) -> Button { 20 | //! Button { 21 | //! text, 22 | //! background_color: catppuccin::PALETTE.mocha.colors.green.hex.to_string(), 23 | //! } 24 | //! } 25 | //! ``` 26 | //! 27 | //! More examples can be found 28 | //! [here](https://github.com/catppuccin/rust/tree/main/examples). 29 | //! 30 | //! # Optional Features 31 | //! 32 | //! ## ANSI string painting 33 | //! 34 | //! Enable the `ansi-term` feature to add the 35 | //! [`Color::ansi_paint`](Color::ansi_paint) method. 36 | //! This adds [ansi-term](https://crates.io/crates/ansi_term) as a dependency. 37 | //! 38 | //! Example: [`examples/term_grid.rs`](https://github.com/catppuccin/rust/blob/main/examples/term_grid.rs) 39 | //! 40 | //! ### CSS colors 41 | //! 42 | //! Enable the `css-colors` feature to enable the conversion of Catppuccin colors to 43 | //! [`css_colors::RGB`] instances. 44 | //! This adds [css-colors](https://crates.io/crates/css-colors) as a dependency. 45 | //! 46 | //! Example: [`examples/css.rs`](https://github.com/catppuccin/rust/blob/main/examples/css.rs) 47 | //! 48 | //! ### Ratatui 49 | //! 50 | //! Enable the `ratatui` feature to enable the conversion of Catppuccin colors to 51 | //! [`ratatui::style::Color`] instances. 52 | //! This adds [ratatui](https://crates.io/crates/ratatui) as a dependency. 53 | //! 54 | //! Example: [`examples/ratatui.rs`](https://github.com/catppuccin/rust/blob/main/examples/ratatui.rs) 55 | //! 56 | //! ### Serde 57 | //! 58 | //! Enable the `serde` feature to enable the serialization of Catppuccin's palette, 59 | //! flavor, and color types. 60 | //! This adds [serde](https://crates.io/crates/serde) as a dependency. 61 | //! 62 | //! Example: [`examples/serde.rs`](https://github.com/catppuccin/rust/blob/main/examples/serde.rs) 63 | use std::{fmt, marker::PhantomData, ops::Index, str::FromStr}; 64 | 65 | include!(concat!(env!("OUT_DIR"), "/generated_palette.rs")); 66 | 67 | /// The top-level type that encompasses the Catppuccin palette data structure. 68 | /// Primarily used via the [`PALETTE`] constant. 69 | /// 70 | /// Can be iterated over, in which case the flavors are yielded in the canonical order: 71 | /// Latte, Frappé, Macchiato, Mocha. 72 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 73 | pub struct Palette { 74 | /// The light flavor. 75 | pub latte: Flavor, 76 | /// The lightest dark flavor. 77 | pub frappe: Flavor, 78 | /// The medium dark flavor. 79 | pub macchiato: Flavor, 80 | /// The darkest dark flavor. 81 | pub mocha: Flavor, 82 | } 83 | 84 | /// Enum of all four flavors of Catppuccin. Can be used to index [`Palette`]. 85 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] 86 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 87 | pub enum FlavorName { 88 | /// The light flavor. 89 | Latte, 90 | /// The lightest dark flavor. 91 | #[cfg_attr(feature = "serde", serde(rename = "Frappé"))] 92 | Frappe, 93 | /// The medium dark flavor. 94 | Macchiato, 95 | /// The darkest dark flavor. 96 | Mocha, 97 | } 98 | 99 | /// An iterator over flavors in the palette. 100 | /// Obtained via [`Palette::iter()`]. 101 | pub struct FlavorIterator<'a> { 102 | current: usize, 103 | phantom: PhantomData<&'a ()>, 104 | } 105 | 106 | /// Color represented as individual red, green, and blue channels. 107 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] 108 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 109 | pub struct Rgb { 110 | /// Red channel. 111 | pub r: u8, 112 | /// Green channel. 113 | pub g: u8, 114 | /// Blue channel. 115 | pub b: u8, 116 | } 117 | 118 | /// Color represented as 6-digit hexadecimal. 119 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] 120 | pub struct Hex(Rgb); 121 | 122 | /// Color represented as individual hue (0-359), saturation (0-1), and lightness (0-1) channels. 123 | #[derive(Clone, Copy, Debug, PartialEq)] 124 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 125 | pub struct Hsl { 126 | /// Hue channel. 127 | pub h: f64, 128 | /// Saturation channel. 129 | pub s: f64, 130 | /// Lightness channel. 131 | pub l: f64, 132 | } 133 | 134 | /// A single color in the Catppuccin palette. 135 | #[derive(Clone, Copy, Debug, PartialEq)] 136 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 137 | pub struct Color { 138 | /// The [`ColorName`] for this color. 139 | pub name: ColorName, 140 | /// Order of the color in the palette spec. 141 | pub order: u32, 142 | /// Whether the color is considered an accent color. 143 | /// Accent colors are the first 14 colors in the palette, also called 144 | /// the analogous colours. The remaining 12 non-accent colors are also 145 | /// referred to as the monochromatic colors. 146 | pub accent: bool, 147 | /// The color represented as a six-digit hex string with a leading hash (#). 148 | pub hex: Hex, 149 | /// The color represented as individual red, green, and blue channels. 150 | pub rgb: Rgb, 151 | /// The color represented as individual hue, saturation, and lightness channels. 152 | pub hsl: Hsl, 153 | } 154 | 155 | /// A flavor is a collection of colors. Catppuccin has four flavors; Latte, 156 | /// Frappé, Macchiato, and Mocha. 157 | /// 158 | /// Can be iterated over, in which case the colors are yielded in order. 159 | #[derive(Clone, Copy, Debug, PartialEq)] 160 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 161 | pub struct Flavor { 162 | /// The name of the flavor. 163 | pub name: FlavorName, 164 | /// Emoji associated with the flavor. Requires Unicode 13.0 (2020) or later to render. 165 | pub emoji: char, 166 | /// Order of the flavor in the palette spec. 167 | pub order: u32, 168 | /// Whether this flavor is dark or light oriented. Latte is light, the other 169 | /// three flavors are dark. 170 | pub dark: bool, 171 | /// The colors in the flavor. 172 | pub colors: FlavorColors, 173 | /// The ANSI colors in the flavor. 174 | pub ansi_colors: FlavorAnsiColors, 175 | } 176 | 177 | /// An iterator over colors in a flavor. 178 | /// Obtained via [`Flavor::into_iter()`](struct.Flavor.html#method.into_iter) or [`FlavorColors::iter()`]. 179 | pub struct ColorIterator<'a> { 180 | colors: &'a FlavorColors, 181 | current: usize, 182 | } 183 | 184 | /// An iterator over the ANSI colors in a flavor. 185 | /// 186 | /// Defaults to ascending order by ANSI code 0 -> 16. 187 | /// Obtained via [`FlavorAnsiColors::into_iter()`](struct.FlavorAnsiColors.html#method.into_iter) or [`FlavorAnsiColors::iter()`]. 188 | pub struct AnsiColorIterator<'a> { 189 | ansi_colors: &'a FlavorAnsiColors, 190 | current: usize, 191 | } 192 | 193 | /// An iterator over the ANSI color pairs in a flavor. 194 | /// Obtained via [`FlavorAnsiColorPairs::into_iter()`](struct.FlavorAnsiColorPairs.html#method.into_iter) or [`FlavorAnsiColorPairs::iter()`]. 195 | pub struct AnsiColorPairsIterator<'a> { 196 | ansi_color_pairs: &'a FlavorAnsiColorPairs, 197 | current: usize, 198 | } 199 | 200 | impl Palette { 201 | /// Get an array of the flavors in the palette. 202 | #[must_use] 203 | pub const fn all_flavors(&self) -> [&Flavor; 4] { 204 | [&self.latte, &self.frappe, &self.macchiato, &self.mocha] 205 | } 206 | 207 | /// Create an iterator over the flavors in the palette. 208 | #[must_use] 209 | pub const fn iter(&self) -> FlavorIterator { 210 | FlavorIterator { 211 | current: 0, 212 | phantom: PhantomData, 213 | } 214 | } 215 | } 216 | 217 | impl Index for Palette { 218 | type Output = Flavor; 219 | 220 | fn index(&self, index: FlavorName) -> &Self::Output { 221 | match index { 222 | FlavorName::Latte => &self.latte, 223 | FlavorName::Frappe => &self.frappe, 224 | FlavorName::Macchiato => &self.macchiato, 225 | FlavorName::Mocha => &self.mocha, 226 | } 227 | } 228 | } 229 | 230 | impl Palette { 231 | /// Get a flavor by name. 232 | /// 233 | /// This is equivalent to using the index operator, but can also be used in 234 | /// const contexts. 235 | #[must_use] 236 | pub const fn get_flavor(&self, name: FlavorName) -> &Flavor { 237 | match name { 238 | FlavorName::Latte => &self.latte, 239 | FlavorName::Frappe => &self.frappe, 240 | FlavorName::Macchiato => &self.macchiato, 241 | FlavorName::Mocha => &self.mocha, 242 | } 243 | } 244 | } 245 | 246 | impl fmt::Display for Hex { 247 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 248 | let Rgb { r, g, b } = self.0; 249 | write!(f, "#{r:02x}{g:02x}{b:02x}") 250 | } 251 | } 252 | 253 | #[cfg(feature = "serde")] 254 | mod _hex { 255 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 256 | 257 | use crate::{Hex, Rgb}; 258 | 259 | impl Serialize for Hex { 260 | fn serialize(&self, serializer: S) -> Result 261 | where 262 | S: Serializer, 263 | { 264 | serializer.serialize_str(&self.to_string()) 265 | } 266 | } 267 | 268 | impl<'de> Deserialize<'de> for Hex { 269 | fn deserialize(deserializer: D) -> Result 270 | where 271 | D: Deserializer<'de>, 272 | { 273 | let hex: String = Deserialize::deserialize(deserializer)?; 274 | let hex: u32 = u32::from_str_radix(hex.trim_start_matches('#'), 16) 275 | .map_err(serde::de::Error::custom)?; 276 | let r = ((hex >> 16) & 0xff) as u8; 277 | let g = ((hex >> 8) & 0xff) as u8; 278 | let b = (hex & 0xff) as u8; 279 | Ok(Self(Rgb { r, g, b })) 280 | } 281 | } 282 | } 283 | 284 | impl fmt::Display for FlavorName { 285 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 286 | match self { 287 | Self::Latte => write!(f, "Latte"), 288 | Self::Frappe => write!(f, "Frappé"), 289 | Self::Macchiato => write!(f, "Macchiato"), 290 | Self::Mocha => write!(f, "Mocha"), 291 | } 292 | } 293 | } 294 | 295 | /// Error type for parsing a [`FlavorName`] from a string. 296 | #[derive(Debug, PartialEq, Eq)] 297 | pub struct ParseFlavorNameError; 298 | impl std::error::Error for ParseFlavorNameError {} 299 | impl std::fmt::Display for ParseFlavorNameError { 300 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 301 | write!( 302 | f, 303 | "invalid flavor identifier, expected one of: latte, frappe, frappé, macchiato, mocha" 304 | ) 305 | } 306 | } 307 | 308 | impl FromStr for FlavorName { 309 | type Err = ParseFlavorNameError; 310 | 311 | fn from_str(s: &str) -> Result { 312 | match s { 313 | "latte" => Ok(Self::Latte), 314 | "frappe" | "frappé" => Ok(Self::Frappe), 315 | "macchiato" => Ok(Self::Macchiato), 316 | "mocha" => Ok(Self::Mocha), 317 | _ => Err(ParseFlavorNameError), 318 | } 319 | } 320 | } 321 | 322 | impl FlavorName { 323 | /// Get the flavor's identifier; the lowercase key used to identify the flavor. 324 | /// This differs from `to_string` in that it's intended for machine usage 325 | /// rather than presentation. 326 | /// 327 | /// Example: 328 | /// 329 | /// ```rust 330 | /// let frappe = catppuccin::PALETTE.frappe; 331 | /// assert_eq!(frappe.name.to_string(), "Frappé"); 332 | /// assert_eq!(frappe.name.identifier(), "frappe"); 333 | /// ``` 334 | #[must_use] 335 | pub const fn identifier(&self) -> &'static str { 336 | match self { 337 | Self::Latte => "latte", 338 | Self::Frappe => "frappe", 339 | Self::Macchiato => "macchiato", 340 | Self::Mocha => "mocha", 341 | } 342 | } 343 | } 344 | 345 | impl FlavorColors { 346 | /// Create an iterator over the colors in the flavor. 347 | #[must_use] 348 | pub const fn iter(&self) -> ColorIterator { 349 | ColorIterator { 350 | colors: self, 351 | current: 0, 352 | } 353 | } 354 | } 355 | 356 | impl FlavorAnsiColors { 357 | /// Create an iterator over the ANSI colors in the flavor. 358 | #[must_use] 359 | pub const fn iter(&self) -> AnsiColorIterator { 360 | AnsiColorIterator { 361 | ansi_colors: self, 362 | current: 0, 363 | } 364 | } 365 | 366 | /// Get the ANSI color pairs 367 | #[must_use] 368 | pub const fn all_pairs(&self) -> FlavorAnsiColorPairs { 369 | self.to_ansi_color_pairs() 370 | } 371 | } 372 | 373 | impl FlavorAnsiColorPairs { 374 | /// Create an iterator over the ANSI color pairs in the flavor. 375 | #[must_use] 376 | pub const fn iter(&self) -> AnsiColorPairsIterator { 377 | AnsiColorPairsIterator { 378 | ansi_color_pairs: self, 379 | current: 0, 380 | } 381 | } 382 | } 383 | 384 | impl<'a> Iterator for FlavorIterator<'a> { 385 | type Item = &'a Flavor; 386 | 387 | fn next(&mut self) -> Option { 388 | if self.current >= PALETTE.all_flavors().len() { 389 | None 390 | } else { 391 | let flavor = PALETTE.all_flavors()[self.current]; 392 | self.current += 1; 393 | Some(flavor) 394 | } 395 | } 396 | } 397 | 398 | impl<'a> Iterator for ColorIterator<'a> { 399 | type Item = &'a Color; 400 | 401 | fn next(&mut self) -> Option { 402 | if self.current >= self.colors.all_colors().len() { 403 | None 404 | } else { 405 | let color = self.colors.all_colors()[self.current]; 406 | self.current += 1; 407 | Some(color) 408 | } 409 | } 410 | } 411 | 412 | impl<'a> Iterator for AnsiColorIterator<'a> { 413 | type Item = &'a AnsiColor; 414 | 415 | fn next(&mut self) -> Option { 416 | if self.current >= self.ansi_colors.all_ansi_colors().len() { 417 | None 418 | } else { 419 | let color = self.ansi_colors.all_ansi_colors()[self.current]; 420 | self.current += 1; 421 | Some(color) 422 | } 423 | } 424 | } 425 | 426 | impl<'a> Iterator for AnsiColorPairsIterator<'a> { 427 | type Item = &'a AnsiColorPair; 428 | 429 | fn next(&mut self) -> Option { 430 | if self.current >= self.ansi_color_pairs.all_ansi_color_pairs().len() { 431 | None 432 | } else { 433 | let color = self.ansi_color_pairs.all_ansi_color_pairs()[self.current]; 434 | self.current += 1; 435 | Some(color) 436 | } 437 | } 438 | } 439 | 440 | impl<'a> IntoIterator for &'a Palette { 441 | type Item = &'a Flavor; 442 | type IntoIter = FlavorIterator<'a>; 443 | 444 | fn into_iter(self) -> Self::IntoIter { 445 | self.iter() 446 | } 447 | } 448 | 449 | impl<'a> IntoIterator for &'a FlavorColors { 450 | type Item = &'a Color; 451 | type IntoIter = ColorIterator<'a>; 452 | 453 | fn into_iter(self) -> Self::IntoIter { 454 | self.iter() 455 | } 456 | } 457 | 458 | impl<'a> IntoIterator for &'a FlavorAnsiColors { 459 | type Item = &'a AnsiColor; 460 | type IntoIter = AnsiColorIterator<'a>; 461 | 462 | fn into_iter(self) -> Self::IntoIter { 463 | self.iter() 464 | } 465 | } 466 | 467 | impl<'a> IntoIterator for &'a FlavorAnsiColorPairs { 468 | type Item = &'a AnsiColorPair; 469 | type IntoIter = AnsiColorPairsIterator<'a>; 470 | 471 | fn into_iter(self) -> Self::IntoIter { 472 | self.iter() 473 | } 474 | } 475 | 476 | impl Flavor { 477 | /// Create an iterator over the colors in the flavor. 478 | #[must_use] 479 | pub const fn iter(&self) -> ColorIterator { 480 | self.colors.iter() 481 | } 482 | 483 | /// Equivalent to [`.name.identifier()`](FlavorName::identifier). 484 | #[must_use] 485 | pub const fn identifier(&self) -> &'static str { 486 | self.name.identifier() 487 | } 488 | } 489 | 490 | impl<'a> IntoIterator for &'a Flavor { 491 | type Item = &'a Color; 492 | type IntoIter = ColorIterator<'a>; 493 | 494 | fn into_iter(self) -> Self::IntoIter { 495 | self.colors.iter() 496 | } 497 | } 498 | 499 | /// Error type for parsing a [`ColorName`] from a string. 500 | #[derive(Debug, PartialEq, Eq)] 501 | pub struct ParseColorNameError; 502 | impl std::error::Error for ParseColorNameError {} 503 | impl std::fmt::Display for ParseColorNameError { 504 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 505 | write!(f, "invalid color identifier") 506 | } 507 | } 508 | 509 | impl Index for Flavor { 510 | type Output = Color; 511 | 512 | fn index(&self, index: ColorName) -> &Self::Output { 513 | self.colors.index(index) 514 | } 515 | } 516 | 517 | impl Flavor { 518 | /// Get a color by name. 519 | /// 520 | /// This is equivalent to using the index operator, but can also be used in 521 | /// const contexts. 522 | #[must_use] 523 | pub const fn get_color(&self, name: ColorName) -> &Color { 524 | self.colors.get_color(name) 525 | } 526 | } 527 | 528 | impl Color { 529 | /// Equivalent to [`.name.identifier()`](ColorName::identifier). 530 | #[must_use] 531 | pub const fn identifier(&self) -> &'static str { 532 | self.name.identifier() 533 | } 534 | } 535 | 536 | impl From<(u8, u8, u8)> for Rgb { 537 | fn from((r, g, b): (u8, u8, u8)) -> Self { 538 | Self { r, g, b } 539 | } 540 | } 541 | 542 | impl From<(u8, u8, u8)> for Hex { 543 | fn from((r, g, b): (u8, u8, u8)) -> Self { 544 | Self(Rgb { r, g, b }) 545 | } 546 | } 547 | 548 | impl From<(f64, f64, f64)> for Hsl { 549 | fn from((h, s, l): (f64, f64, f64)) -> Self { 550 | Self { h, s, l } 551 | } 552 | } 553 | 554 | #[cfg(feature = "css-colors")] 555 | mod css_colors { 556 | use crate::{AnsiColor, Color}; 557 | 558 | impl From for css_colors::RGB { 559 | fn from(value: Color) -> Self { 560 | Self { 561 | r: css_colors::Ratio::from_u8(value.rgb.r), 562 | g: css_colors::Ratio::from_u8(value.rgb.g), 563 | b: css_colors::Ratio::from_u8(value.rgb.b), 564 | } 565 | } 566 | } 567 | 568 | impl From for css_colors::RGB { 569 | fn from(value: AnsiColor) -> Self { 570 | Self { 571 | r: css_colors::Ratio::from_u8(value.rgb.r), 572 | g: css_colors::Ratio::from_u8(value.rgb.g), 573 | b: css_colors::Ratio::from_u8(value.rgb.b), 574 | } 575 | } 576 | } 577 | 578 | impl From for css_colors::HSL { 579 | fn from(value: Color) -> Self { 580 | #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] 581 | Self { 582 | h: css_colors::Angle::new(value.hsl.h as u16), 583 | s: css_colors::Ratio::from_f32(value.hsl.s as f32), 584 | l: css_colors::Ratio::from_f32(value.hsl.l as f32), 585 | } 586 | } 587 | } 588 | 589 | impl From for css_colors::HSL { 590 | fn from(value: AnsiColor) -> Self { 591 | #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] 592 | Self { 593 | h: css_colors::Angle::new(value.hsl.h as u16), 594 | s: css_colors::Ratio::from_f32(value.hsl.s as f32), 595 | l: css_colors::Ratio::from_f32(value.hsl.l as f32), 596 | } 597 | } 598 | } 599 | } 600 | 601 | #[cfg(feature = "ansi-term")] 602 | mod ansi_term { 603 | use crate::{AnsiColor, Color}; 604 | 605 | impl Color { 606 | /// Paints the given input with a color à la [ansi_term](https://docs.rs/ansi_term/latest/ansi_term/) 607 | pub fn ansi_paint<'a, I, S: 'a + ToOwned + ?Sized>( 608 | &self, 609 | input: I, 610 | ) -> ansi_term::ANSIGenericString<'a, S> 611 | where 612 | I: Into>, 613 | ::Owned: core::fmt::Debug, 614 | { 615 | ansi_term::Color::RGB(self.rgb.r, self.rgb.g, self.rgb.b).paint(input) 616 | } 617 | } 618 | 619 | impl AnsiColor { 620 | /// Paints the given input with a color à la [ansi_term](https://docs.rs/ansi_term/latest/ansi_term/) 621 | pub fn ansi_paint<'a, I, S: 'a + ToOwned + ?Sized>( 622 | &self, 623 | input: I, 624 | ) -> ansi_term::ANSIGenericString<'a, S> 625 | where 626 | I: Into>, 627 | ::Owned: core::fmt::Debug, 628 | { 629 | ansi_term::Color::RGB(self.rgb.r, self.rgb.g, self.rgb.b).paint(input) 630 | } 631 | } 632 | } 633 | 634 | #[cfg(feature = "ratatui")] 635 | mod ratatui { 636 | use crate::{AnsiColor, Color}; 637 | 638 | impl From for ratatui::style::Color { 639 | fn from(value: Color) -> Self { 640 | Self::Rgb(value.rgb.r, value.rgb.g, value.rgb.b) 641 | } 642 | } 643 | 644 | impl From for ratatui::style::Color { 645 | fn from(value: AnsiColor) -> Self { 646 | Self::Rgb(value.rgb.r, value.rgb.g, value.rgb.b) 647 | } 648 | } 649 | } 650 | -------------------------------------------------------------------------------- /src/palette.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.7.1", 3 | "latte": { 4 | "name": "Latte", 5 | "emoji": "🌻", 6 | "order": 0, 7 | "dark": false, 8 | "colors": { 9 | "rosewater": { 10 | "name": "Rosewater", 11 | "order": 0, 12 | "hex": "#dc8a78", 13 | "rgb": { 14 | "r": 220, 15 | "g": 138, 16 | "b": 120 17 | }, 18 | "hsl": { 19 | "h": 10.799999999999995, 20 | "s": 0.5882352941176472, 21 | "l": 0.6666666666666667 22 | }, 23 | "accent": true 24 | }, 25 | "flamingo": { 26 | "name": "Flamingo", 27 | "order": 1, 28 | "hex": "#dd7878", 29 | "rgb": { 30 | "r": 221, 31 | "g": 120, 32 | "b": 120 33 | }, 34 | "hsl": { 35 | "h": 0, 36 | "s": 0.5976331360946746, 37 | "l": 0.6686274509803922 38 | }, 39 | "accent": true 40 | }, 41 | "pink": { 42 | "name": "Pink", 43 | "order": 2, 44 | "hex": "#ea76cb", 45 | "rgb": { 46 | "r": 234, 47 | "g": 118, 48 | "b": 203 49 | }, 50 | "hsl": { 51 | "h": 316.0344827586207, 52 | "s": 0.7341772151898731, 53 | "l": 0.6901960784313725 54 | }, 55 | "accent": true 56 | }, 57 | "mauve": { 58 | "name": "Mauve", 59 | "order": 3, 60 | "hex": "#8839ef", 61 | "rgb": { 62 | "r": 136, 63 | "g": 57, 64 | "b": 239 65 | }, 66 | "hsl": { 67 | "h": 266.0439560439561, 68 | "s": 0.8504672897196262, 69 | "l": 0.5803921568627451 70 | }, 71 | "accent": true 72 | }, 73 | "red": { 74 | "name": "Red", 75 | "order": 4, 76 | "hex": "#d20f39", 77 | "rgb": { 78 | "r": 210, 79 | "g": 15, 80 | "b": 57 81 | }, 82 | "hsl": { 83 | "h": 347.0769230769231, 84 | "s": 0.8666666666666666, 85 | "l": 0.4411764705882353 86 | }, 87 | "accent": true 88 | }, 89 | "maroon": { 90 | "name": "Maroon", 91 | "order": 5, 92 | "hex": "#e64553", 93 | "rgb": { 94 | "r": 230, 95 | "g": 69, 96 | "b": 83 97 | }, 98 | "hsl": { 99 | "h": 354.78260869565213, 100 | "s": 0.76303317535545, 101 | "l": 0.5862745098039216 102 | }, 103 | "accent": true 104 | }, 105 | "peach": { 106 | "name": "Peach", 107 | "order": 6, 108 | "hex": "#fe640b", 109 | "rgb": { 110 | "r": 254, 111 | "g": 100, 112 | "b": 11 113 | }, 114 | "hsl": { 115 | "h": 21.975308641975307, 116 | "s": 0.9918367346938776, 117 | "l": 0.5196078431372549 118 | }, 119 | "accent": true 120 | }, 121 | "yellow": { 122 | "name": "Yellow", 123 | "order": 7, 124 | "hex": "#df8e1d", 125 | "rgb": { 126 | "r": 223, 127 | "g": 142, 128 | "b": 29 129 | }, 130 | "hsl": { 131 | "h": 34.948453608247426, 132 | "s": 0.7698412698412698, 133 | "l": 0.49411764705882355 134 | }, 135 | "accent": true 136 | }, 137 | "green": { 138 | "name": "Green", 139 | "order": 8, 140 | "hex": "#40a02b", 141 | "rgb": { 142 | "r": 64, 143 | "g": 160, 144 | "b": 43 145 | }, 146 | "hsl": { 147 | "h": 109.23076923076923, 148 | "s": 0.5763546798029556, 149 | "l": 0.39803921568627454 150 | }, 151 | "accent": true 152 | }, 153 | "teal": { 154 | "name": "Teal", 155 | "order": 9, 156 | "hex": "#179299", 157 | "rgb": { 158 | "r": 23, 159 | "g": 146, 160 | "b": 153 161 | }, 162 | "hsl": { 163 | "h": 183.23076923076923, 164 | "s": 0.7386363636363636, 165 | "l": 0.34509803921568627 166 | }, 167 | "accent": true 168 | }, 169 | "sky": { 170 | "name": "Sky", 171 | "order": 10, 172 | "hex": "#04a5e5", 173 | "rgb": { 174 | "r": 4, 175 | "g": 165, 176 | "b": 229 177 | }, 178 | "hsl": { 179 | "h": 197.0666666666667, 180 | "s": 0.965665236051502, 181 | "l": 0.45686274509803926 182 | }, 183 | "accent": true 184 | }, 185 | "sapphire": { 186 | "name": "Sapphire", 187 | "order": 11, 188 | "hex": "#209fb5", 189 | "rgb": { 190 | "r": 32, 191 | "g": 159, 192 | "b": 181 193 | }, 194 | "hsl": { 195 | "h": 188.85906040268458, 196 | "s": 0.6995305164319249, 197 | "l": 0.4176470588235294 198 | }, 199 | "accent": true 200 | }, 201 | "blue": { 202 | "name": "Blue", 203 | "order": 12, 204 | "hex": "#1e66f5", 205 | "rgb": { 206 | "r": 30, 207 | "g": 102, 208 | "b": 245 209 | }, 210 | "hsl": { 211 | "h": 219.90697674418607, 212 | "s": 0.9148936170212768, 213 | "l": 0.5392156862745098 214 | }, 215 | "accent": true 216 | }, 217 | "lavender": { 218 | "name": "Lavender", 219 | "order": 13, 220 | "hex": "#7287fd", 221 | "rgb": { 222 | "r": 114, 223 | "g": 135, 224 | "b": 253 225 | }, 226 | "hsl": { 227 | "h": 230.93525179856115, 228 | "s": 0.9720279720279721, 229 | "l": 0.7196078431372549 230 | }, 231 | "accent": true 232 | }, 233 | "text": { 234 | "name": "Text", 235 | "order": 14, 236 | "hex": "#4c4f69", 237 | "rgb": { 238 | "r": 76, 239 | "g": 79, 240 | "b": 105 241 | }, 242 | "hsl": { 243 | "h": 233.79310344827587, 244 | "s": 0.16022099447513813, 245 | "l": 0.3549019607843137 246 | }, 247 | "accent": false 248 | }, 249 | "subtext1": { 250 | "name": "Subtext 1", 251 | "order": 15, 252 | "hex": "#5c5f77", 253 | "rgb": { 254 | "r": 92, 255 | "g": 95, 256 | "b": 119 257 | }, 258 | "hsl": { 259 | "h": 233.33333333333334, 260 | "s": 0.1279620853080569, 261 | "l": 0.4137254901960784 262 | }, 263 | "accent": false 264 | }, 265 | "subtext0": { 266 | "name": "Subtext 0", 267 | "order": 16, 268 | "hex": "#6c6f85", 269 | "rgb": { 270 | "r": 108, 271 | "g": 111, 272 | "b": 133 273 | }, 274 | "hsl": { 275 | "h": 232.79999999999998, 276 | "s": 0.10373443983402494, 277 | "l": 0.4725490196078431 278 | }, 279 | "accent": false 280 | }, 281 | "overlay2": { 282 | "name": "Overlay 2", 283 | "order": 17, 284 | "hex": "#7c7f93", 285 | "rgb": { 286 | "r": 124, 287 | "g": 127, 288 | "b": 147 289 | }, 290 | "hsl": { 291 | "h": 232.17391304347825, 292 | "s": 0.09623430962343092, 293 | "l": 0.5313725490196078 294 | }, 295 | "accent": false 296 | }, 297 | "overlay1": { 298 | "name": "Overlay 1", 299 | "order": 18, 300 | "hex": "#8c8fa1", 301 | "rgb": { 302 | "r": 140, 303 | "g": 143, 304 | "b": 161 305 | }, 306 | "hsl": { 307 | "h": 231.42857142857144, 308 | "s": 0.10047846889952144, 309 | "l": 0.5901960784313726 310 | }, 311 | "accent": false 312 | }, 313 | "overlay0": { 314 | "name": "Overlay 0", 315 | "order": 19, 316 | "hex": "#9ca0b0", 317 | "rgb": { 318 | "r": 156, 319 | "g": 160, 320 | "b": 176 321 | }, 322 | "hsl": { 323 | "h": 228.00000000000003, 324 | "s": 0.11235955056179768, 325 | "l": 0.6509803921568628 326 | }, 327 | "accent": false 328 | }, 329 | "surface2": { 330 | "name": "Surface 2", 331 | "order": 20, 332 | "hex": "#acb0be", 333 | "rgb": { 334 | "r": 172, 335 | "g": 176, 336 | "b": 190 337 | }, 338 | "hsl": { 339 | "h": 226.6666666666667, 340 | "s": 0.12162162162162159, 341 | "l": 0.7098039215686275 342 | }, 343 | "accent": false 344 | }, 345 | "surface1": { 346 | "name": "Surface 1", 347 | "order": 21, 348 | "hex": "#bcc0cc", 349 | "rgb": { 350 | "r": 188, 351 | "g": 192, 352 | "b": 204 353 | }, 354 | "hsl": { 355 | "h": 225.00000000000003, 356 | "s": 0.13559322033898308, 357 | "l": 0.7686274509803922 358 | }, 359 | "accent": false 360 | }, 361 | "surface0": { 362 | "name": "Surface 0", 363 | "order": 22, 364 | "hex": "#ccd0da", 365 | "rgb": { 366 | "r": 204, 367 | "g": 208, 368 | "b": 218 369 | }, 370 | "hsl": { 371 | "h": 222.85714285714292, 372 | "s": 0.1590909090909089, 373 | "l": 0.8274509803921568 374 | }, 375 | "accent": false 376 | }, 377 | "base": { 378 | "name": "Base", 379 | "order": 23, 380 | "hex": "#eff1f5", 381 | "rgb": { 382 | "r": 239, 383 | "g": 241, 384 | "b": 245 385 | }, 386 | "hsl": { 387 | "h": 220.00000000000009, 388 | "s": 0.23076923076923136, 389 | "l": 0.9490196078431372 390 | }, 391 | "accent": false 392 | }, 393 | "mantle": { 394 | "name": "Mantle", 395 | "order": 24, 396 | "hex": "#e6e9ef", 397 | "rgb": { 398 | "r": 230, 399 | "g": 233, 400 | "b": 239 401 | }, 402 | "hsl": { 403 | "h": 220.00000000000006, 404 | "s": 0.21951219512195116, 405 | "l": 0.919607843137255 406 | }, 407 | "accent": false 408 | }, 409 | "crust": { 410 | "name": "Crust", 411 | "order": 25, 412 | "hex": "#dce0e8", 413 | "rgb": { 414 | "r": 220, 415 | "g": 224, 416 | "b": 232 417 | }, 418 | "hsl": { 419 | "h": 220.00000000000006, 420 | "s": 0.20689655172413762, 421 | "l": 0.8862745098039215 422 | }, 423 | "accent": false 424 | } 425 | }, 426 | "ansiColors": { 427 | "black": { 428 | "name": "Black", 429 | "order": 0, 430 | "normal": { 431 | "name": "Black", 432 | "hex": "#5c5f77", 433 | "rgb": { 434 | "r": 92, 435 | "g": 95, 436 | "b": 119 437 | }, 438 | "hsl": { 439 | "h": 233.33333333333334, 440 | "s": 0.1279620853080569, 441 | "l": 0.4137254901960784 442 | }, 443 | "code": 0 444 | }, 445 | "bright": { 446 | "name": "Bright Black", 447 | "hex": "#6c6f85", 448 | "rgb": { 449 | "r": 108, 450 | "g": 111, 451 | "b": 133 452 | }, 453 | "hsl": { 454 | "h": 232.79999999999998, 455 | "s": 0.10373443983402494, 456 | "l": 0.4725490196078431 457 | }, 458 | "code": 8 459 | } 460 | }, 461 | "red": { 462 | "name": "Red", 463 | "order": 1, 464 | "normal": { 465 | "name": "Red", 466 | "hex": "#d20f39", 467 | "rgb": { 468 | "r": 210, 469 | "g": 15, 470 | "b": 57 471 | }, 472 | "hsl": { 473 | "h": 347.0769230769231, 474 | "s": 0.8666666666666666, 475 | "l": 0.4411764705882353 476 | }, 477 | "code": 1 478 | }, 479 | "bright": { 480 | "name": "Bright Red", 481 | "hex": "#de293e", 482 | "rgb": { 483 | "r": 222, 484 | "g": 41, 485 | "b": 62 486 | }, 487 | "hsl": { 488 | "h": 353.0386740331492, 489 | "s": 0.7327935222672065, 490 | "l": 0.515686274509804 491 | }, 492 | "code": 9 493 | } 494 | }, 495 | "green": { 496 | "name": "Green", 497 | "order": 2, 498 | "normal": { 499 | "name": "Green", 500 | "hex": "#40a02b", 501 | "rgb": { 502 | "r": 64, 503 | "g": 160, 504 | "b": 43 505 | }, 506 | "hsl": { 507 | "h": 109.23076923076923, 508 | "s": 0.5763546798029556, 509 | "l": 0.39803921568627454 510 | }, 511 | "code": 2 512 | }, 513 | "bright": { 514 | "name": "Bright Green", 515 | "hex": "#49af3d", 516 | "rgb": { 517 | "r": 73, 518 | "g": 175, 519 | "b": 61 520 | }, 521 | "hsl": { 522 | "h": 113.68421052631581, 523 | "s": 0.48305084745762705, 524 | "l": 0.4627450980392157 525 | }, 526 | "code": 10 527 | } 528 | }, 529 | "yellow": { 530 | "name": "Yellow", 531 | "order": 3, 532 | "normal": { 533 | "name": "Yellow", 534 | "hex": "#df8e1d", 535 | "rgb": { 536 | "r": 223, 537 | "g": 142, 538 | "b": 29 539 | }, 540 | "hsl": { 541 | "h": 34.948453608247426, 542 | "s": 0.7698412698412698, 543 | "l": 0.49411764705882355 544 | }, 545 | "code": 3 546 | }, 547 | "bright": { 548 | "name": "Bright Yellow", 549 | "hex": "#eea02d", 550 | "rgb": { 551 | "r": 238, 552 | "g": 160, 553 | "b": 45 554 | }, 555 | "hsl": { 556 | "h": 35.751295336787564, 557 | "s": 0.8502202643171807, 558 | "l": 0.5549019607843138 559 | }, 560 | "code": 11 561 | } 562 | }, 563 | "blue": { 564 | "name": "Blue", 565 | "order": 4, 566 | "normal": { 567 | "name": "Blue", 568 | "hex": "#1e66f5", 569 | "rgb": { 570 | "r": 30, 571 | "g": 102, 572 | "b": 245 573 | }, 574 | "hsl": { 575 | "h": 219.90697674418607, 576 | "s": 0.9148936170212768, 577 | "l": 0.5392156862745098 578 | }, 579 | "code": 4 580 | }, 581 | "bright": { 582 | "name": "Bright Blue", 583 | "hex": "#456eff", 584 | "rgb": { 585 | "r": 69, 586 | "g": 110, 587 | "b": 255 588 | }, 589 | "hsl": { 590 | "h": 226.77419354838707, 591 | "s": 1, 592 | "l": 0.6352941176470588 593 | }, 594 | "code": 12 595 | } 596 | }, 597 | "magenta": { 598 | "name": "Magenta", 599 | "order": 5, 600 | "normal": { 601 | "name": "Magenta", 602 | "hex": "#ea76cb", 603 | "rgb": { 604 | "r": 234, 605 | "g": 118, 606 | "b": 203 607 | }, 608 | "hsl": { 609 | "h": 316.0344827586207, 610 | "s": 0.7341772151898731, 611 | "l": 0.6901960784313725 612 | }, 613 | "code": 5 614 | }, 615 | "bright": { 616 | "name": "Bright Magenta", 617 | "hex": "#fe85d8", 618 | "rgb": { 619 | "r": 254, 620 | "g": 133, 621 | "b": 216 622 | }, 623 | "hsl": { 624 | "h": 318.8429752066116, 625 | "s": 0.983739837398374, 626 | "l": 0.7588235294117647 627 | }, 628 | "code": 13 629 | } 630 | }, 631 | "cyan": { 632 | "name": "Cyan", 633 | "order": 6, 634 | "normal": { 635 | "name": "Cyan", 636 | "hex": "#179299", 637 | "rgb": { 638 | "r": 23, 639 | "g": 146, 640 | "b": 153 641 | }, 642 | "hsl": { 643 | "h": 183.23076923076923, 644 | "s": 0.7386363636363636, 645 | "l": 0.34509803921568627 646 | }, 647 | "code": 6 648 | }, 649 | "bright": { 650 | "name": "Bright Cyan", 651 | "hex": "#2d9fa8", 652 | "rgb": { 653 | "r": 45, 654 | "g": 159, 655 | "b": 168 656 | }, 657 | "hsl": { 658 | "h": 184.39024390243904, 659 | "s": 0.5774647887323943, 660 | "l": 0.4176470588235294 661 | }, 662 | "code": 14 663 | } 664 | }, 665 | "white": { 666 | "name": "White", 667 | "order": 7, 668 | "normal": { 669 | "name": "White", 670 | "hex": "#acb0be", 671 | "rgb": { 672 | "r": 172, 673 | "g": 176, 674 | "b": 190 675 | }, 676 | "hsl": { 677 | "h": 226.6666666666667, 678 | "s": 0.12162162162162159, 679 | "l": 0.7098039215686275 680 | }, 681 | "code": 7 682 | }, 683 | "bright": { 684 | "name": "Bright White", 685 | "hex": "#bcc0cc", 686 | "rgb": { 687 | "r": 188, 688 | "g": 192, 689 | "b": 204 690 | }, 691 | "hsl": { 692 | "h": 225.00000000000003, 693 | "s": 0.13559322033898308, 694 | "l": 0.7686274509803922 695 | }, 696 | "code": 15 697 | } 698 | } 699 | } 700 | }, 701 | "frappe": { 702 | "name": "Frappé", 703 | "emoji": "🪴", 704 | "order": 1, 705 | "dark": true, 706 | "colors": { 707 | "rosewater": { 708 | "name": "Rosewater", 709 | "order": 0, 710 | "hex": "#f2d5cf", 711 | "rgb": { 712 | "r": 242, 713 | "g": 213, 714 | "b": 207 715 | }, 716 | "hsl": { 717 | "h": 10.2857142857143, 718 | "s": 0.5737704918032784, 719 | "l": 0.8803921568627451 720 | }, 721 | "accent": true 722 | }, 723 | "flamingo": { 724 | "name": "Flamingo", 725 | "order": 1, 726 | "hex": "#eebebe", 727 | "rgb": { 728 | "r": 238, 729 | "g": 190, 730 | "b": 190 731 | }, 732 | "hsl": { 733 | "h": 0, 734 | "s": 0.5853658536585367, 735 | "l": 0.8392156862745098 736 | }, 737 | "accent": true 738 | }, 739 | "pink": { 740 | "name": "Pink", 741 | "order": 2, 742 | "hex": "#f4b8e4", 743 | "rgb": { 744 | "r": 244, 745 | "g": 184, 746 | "b": 228 747 | }, 748 | "hsl": { 749 | "h": 316, 750 | "s": 0.7317073170731713, 751 | "l": 0.8392156862745098 752 | }, 753 | "accent": true 754 | }, 755 | "mauve": { 756 | "name": "Mauve", 757 | "order": 3, 758 | "hex": "#ca9ee6", 759 | "rgb": { 760 | "r": 202, 761 | "g": 158, 762 | "b": 230 763 | }, 764 | "hsl": { 765 | "h": 276.66666666666663, 766 | "s": 0.5901639344262294, 767 | "l": 0.7607843137254902 768 | }, 769 | "accent": true 770 | }, 771 | "red": { 772 | "name": "Red", 773 | "order": 4, 774 | "hex": "#e78284", 775 | "rgb": { 776 | "r": 231, 777 | "g": 130, 778 | "b": 132 779 | }, 780 | "hsl": { 781 | "h": 358.8118811881188, 782 | "s": 0.6778523489932885, 783 | "l": 0.7078431372549019 784 | }, 785 | "accent": true 786 | }, 787 | "maroon": { 788 | "name": "Maroon", 789 | "order": 5, 790 | "hex": "#ea999c", 791 | "rgb": { 792 | "r": 234, 793 | "g": 153, 794 | "b": 156 795 | }, 796 | "hsl": { 797 | "h": 357.77777777777777, 798 | "s": 0.6585365853658534, 799 | "l": 0.7588235294117647 800 | }, 801 | "accent": true 802 | }, 803 | "peach": { 804 | "name": "Peach", 805 | "order": 6, 806 | "hex": "#ef9f76", 807 | "rgb": { 808 | "r": 239, 809 | "g": 159, 810 | "b": 118 811 | }, 812 | "hsl": { 813 | "h": 20.33057851239669, 814 | "s": 0.7908496732026143, 815 | "l": 0.7 816 | }, 817 | "accent": true 818 | }, 819 | "yellow": { 820 | "name": "Yellow", 821 | "order": 7, 822 | "hex": "#e5c890", 823 | "rgb": { 824 | "r": 229, 825 | "g": 200, 826 | "b": 144 827 | }, 828 | "hsl": { 829 | "h": 39.52941176470588, 830 | "s": 0.6204379562043796, 831 | "l": 0.7313725490196079 832 | }, 833 | "accent": true 834 | }, 835 | "green": { 836 | "name": "Green", 837 | "order": 8, 838 | "hex": "#a6d189", 839 | "rgb": { 840 | "r": 166, 841 | "g": 209, 842 | "b": 137 843 | }, 844 | "hsl": { 845 | "h": 95.83333333333331, 846 | "s": 0.4390243902439024, 847 | "l": 0.6784313725490196 848 | }, 849 | "accent": true 850 | }, 851 | "teal": { 852 | "name": "Teal", 853 | "order": 9, 854 | "hex": "#81c8be", 855 | "rgb": { 856 | "r": 129, 857 | "g": 200, 858 | "b": 190 859 | }, 860 | "hsl": { 861 | "h": 171.5492957746479, 862 | "s": 0.3922651933701657, 863 | "l": 0.6450980392156862 864 | }, 865 | "accent": true 866 | }, 867 | "sky": { 868 | "name": "Sky", 869 | "order": 10, 870 | "hex": "#99d1db", 871 | "rgb": { 872 | "r": 153, 873 | "g": 209, 874 | "b": 219 875 | }, 876 | "hsl": { 877 | "h": 189.09090909090907, 878 | "s": 0.47826086956521735, 879 | "l": 0.7294117647058823 880 | }, 881 | "accent": true 882 | }, 883 | "sapphire": { 884 | "name": "Sapphire", 885 | "order": 11, 886 | "hex": "#85c1dc", 887 | "rgb": { 888 | "r": 133, 889 | "g": 193, 890 | "b": 220 891 | }, 892 | "hsl": { 893 | "h": 198.62068965517244, 894 | "s": 0.5541401273885351, 895 | "l": 0.692156862745098 896 | }, 897 | "accent": true 898 | }, 899 | "blue": { 900 | "name": "Blue", 901 | "order": 12, 902 | "hex": "#8caaee", 903 | "rgb": { 904 | "r": 140, 905 | "g": 170, 906 | "b": 238 907 | }, 908 | "hsl": { 909 | "h": 221.6326530612245, 910 | "s": 0.7424242424242424, 911 | "l": 0.7411764705882353 912 | }, 913 | "accent": true 914 | }, 915 | "lavender": { 916 | "name": "Lavender", 917 | "order": 13, 918 | "hex": "#babbf1", 919 | "rgb": { 920 | "r": 186, 921 | "g": 187, 922 | "b": 241 923 | }, 924 | "hsl": { 925 | "h": 238.90909090909093, 926 | "s": 0.6626506024096385, 927 | "l": 0.8372549019607842 928 | }, 929 | "accent": true 930 | }, 931 | "text": { 932 | "name": "Text", 933 | "order": 14, 934 | "hex": "#c6d0f5", 935 | "rgb": { 936 | "r": 198, 937 | "g": 208, 938 | "b": 245 939 | }, 940 | "hsl": { 941 | "h": 227.2340425531915, 942 | "s": 0.7014925373134333, 943 | "l": 0.8686274509803922 944 | }, 945 | "accent": false 946 | }, 947 | "subtext1": { 948 | "name": "Subtext 1", 949 | "order": 15, 950 | "hex": "#b5bfe2", 951 | "rgb": { 952 | "r": 181, 953 | "g": 191, 954 | "b": 226 955 | }, 956 | "hsl": { 957 | "h": 226.66666666666669, 958 | "s": 0.43689320388349495, 959 | "l": 0.7980392156862746 960 | }, 961 | "accent": false 962 | }, 963 | "subtext0": { 964 | "name": "Subtext 0", 965 | "order": 16, 966 | "hex": "#a5adce", 967 | "rgb": { 968 | "r": 165, 969 | "g": 173, 970 | "b": 206 971 | }, 972 | "hsl": { 973 | "h": 228.29268292682926, 974 | "s": 0.2949640287769784, 975 | "l": 0.7274509803921569 976 | }, 977 | "accent": false 978 | }, 979 | "overlay2": { 980 | "name": "Overlay 2", 981 | "order": 17, 982 | "hex": "#949cbb", 983 | "rgb": { 984 | "r": 148, 985 | "g": 156, 986 | "b": 187 987 | }, 988 | "hsl": { 989 | "h": 227.69230769230768, 990 | "s": 0.22285714285714275, 991 | "l": 0.6568627450980392 992 | }, 993 | "accent": false 994 | }, 995 | "overlay1": { 996 | "name": "Overlay 1", 997 | "order": 18, 998 | "hex": "#838ba7", 999 | "rgb": { 1000 | "r": 131, 1001 | "g": 139, 1002 | "b": 167 1003 | }, 1004 | "hsl": { 1005 | "h": 226.66666666666669, 1006 | "s": 0.16981132075471703, 1007 | "l": 0.584313725490196 1008 | }, 1009 | "accent": false 1010 | }, 1011 | "overlay0": { 1012 | "name": "Overlay 0", 1013 | "order": 19, 1014 | "hex": "#737994", 1015 | "rgb": { 1016 | "r": 115, 1017 | "g": 121, 1018 | "b": 148 1019 | }, 1020 | "hsl": { 1021 | "h": 229.0909090909091, 1022 | "s": 0.13360323886639683, 1023 | "l": 0.515686274509804 1024 | }, 1025 | "accent": false 1026 | }, 1027 | "surface2": { 1028 | "name": "Surface 2", 1029 | "order": 20, 1030 | "hex": "#626880", 1031 | "rgb": { 1032 | "r": 98, 1033 | "g": 104, 1034 | "b": 128 1035 | }, 1036 | "hsl": { 1037 | "h": 228.00000000000003, 1038 | "s": 0.1327433628318584, 1039 | "l": 0.44313725490196076 1040 | }, 1041 | "accent": false 1042 | }, 1043 | "surface1": { 1044 | "name": "Surface 1", 1045 | "order": 21, 1046 | "hex": "#51576d", 1047 | "rgb": { 1048 | "r": 81, 1049 | "g": 87, 1050 | "b": 109 1051 | }, 1052 | "hsl": { 1053 | "h": 227.14285714285714, 1054 | "s": 0.14736842105263157, 1055 | "l": 0.37254901960784315 1056 | }, 1057 | "accent": false 1058 | }, 1059 | "surface0": { 1060 | "name": "Surface 0", 1061 | "order": 22, 1062 | "hex": "#414559", 1063 | "rgb": { 1064 | "r": 65, 1065 | "g": 69, 1066 | "b": 89 1067 | }, 1068 | "hsl": { 1069 | "h": 230.00000000000003, 1070 | "s": 0.15584415584415584, 1071 | "l": 0.30196078431372547 1072 | }, 1073 | "accent": false 1074 | }, 1075 | "base": { 1076 | "name": "Base", 1077 | "order": 23, 1078 | "hex": "#303446", 1079 | "rgb": { 1080 | "r": 48, 1081 | "g": 52, 1082 | "b": 70 1083 | }, 1084 | "hsl": { 1085 | "h": 229.0909090909091, 1086 | "s": 0.18644067796610175, 1087 | "l": 0.23137254901960785 1088 | }, 1089 | "accent": false 1090 | }, 1091 | "mantle": { 1092 | "name": "Mantle", 1093 | "order": 24, 1094 | "hex": "#292c3c", 1095 | "rgb": { 1096 | "r": 41, 1097 | "g": 44, 1098 | "b": 60 1099 | }, 1100 | "hsl": { 1101 | "h": 230.52631578947367, 1102 | "s": 0.18811881188118806, 1103 | "l": 0.19803921568627453 1104 | }, 1105 | "accent": false 1106 | }, 1107 | "crust": { 1108 | "name": "Crust", 1109 | "order": 25, 1110 | "hex": "#232634", 1111 | "rgb": { 1112 | "r": 35, 1113 | "g": 38, 1114 | "b": 52 1115 | }, 1116 | "hsl": { 1117 | "h": 229.41176470588238, 1118 | "s": 0.19540229885057467, 1119 | "l": 0.17058823529411765 1120 | }, 1121 | "accent": false 1122 | } 1123 | }, 1124 | "ansiColors": { 1125 | "black": { 1126 | "name": "Black", 1127 | "order": 0, 1128 | "normal": { 1129 | "name": "Black", 1130 | "hex": "#51576d", 1131 | "rgb": { 1132 | "r": 81, 1133 | "g": 87, 1134 | "b": 109 1135 | }, 1136 | "hsl": { 1137 | "h": 227.14285714285714, 1138 | "s": 0.14736842105263157, 1139 | "l": 0.37254901960784315 1140 | }, 1141 | "code": 0 1142 | }, 1143 | "bright": { 1144 | "name": "Bright Black", 1145 | "hex": "#626880", 1146 | "rgb": { 1147 | "r": 98, 1148 | "g": 104, 1149 | "b": 128 1150 | }, 1151 | "hsl": { 1152 | "h": 228.00000000000003, 1153 | "s": 0.1327433628318584, 1154 | "l": 0.44313725490196076 1155 | }, 1156 | "code": 8 1157 | } 1158 | }, 1159 | "red": { 1160 | "name": "Red", 1161 | "order": 1, 1162 | "normal": { 1163 | "name": "Red", 1164 | "hex": "#e78284", 1165 | "rgb": { 1166 | "r": 231, 1167 | "g": 130, 1168 | "b": 132 1169 | }, 1170 | "hsl": { 1171 | "h": 358.8118811881188, 1172 | "s": 0.6778523489932885, 1173 | "l": 0.7078431372549019 1174 | }, 1175 | "code": 1 1176 | }, 1177 | "bright": { 1178 | "name": "Bright Red", 1179 | "hex": "#e67172", 1180 | "rgb": { 1181 | "r": 230, 1182 | "g": 113, 1183 | "b": 114 1184 | }, 1185 | "hsl": { 1186 | "h": 359.4871794871795, 1187 | "s": 0.7005988023952096, 1188 | "l": 0.6725490196078432 1189 | }, 1190 | "code": 9 1191 | } 1192 | }, 1193 | "green": { 1194 | "name": "Green", 1195 | "order": 2, 1196 | "normal": { 1197 | "name": "Green", 1198 | "hex": "#a6d189", 1199 | "rgb": { 1200 | "r": 166, 1201 | "g": 209, 1202 | "b": 137 1203 | }, 1204 | "hsl": { 1205 | "h": 95.83333333333331, 1206 | "s": 0.4390243902439024, 1207 | "l": 0.6784313725490196 1208 | }, 1209 | "code": 2 1210 | }, 1211 | "bright": { 1212 | "name": "Bright Green", 1213 | "hex": "#8ec772", 1214 | "rgb": { 1215 | "r": 142, 1216 | "g": 199, 1217 | "b": 114 1218 | }, 1219 | "hsl": { 1220 | "h": 100.23529411764706, 1221 | "s": 0.431472081218274, 1222 | "l": 0.6137254901960785 1223 | }, 1224 | "code": 10 1225 | } 1226 | }, 1227 | "yellow": { 1228 | "name": "Yellow", 1229 | "order": 3, 1230 | "normal": { 1231 | "name": "Yellow", 1232 | "hex": "#e5c890", 1233 | "rgb": { 1234 | "r": 229, 1235 | "g": 200, 1236 | "b": 144 1237 | }, 1238 | "hsl": { 1239 | "h": 39.52941176470588, 1240 | "s": 0.6204379562043796, 1241 | "l": 0.7313725490196079 1242 | }, 1243 | "code": 3 1244 | }, 1245 | "bright": { 1246 | "name": "Bright Yellow", 1247 | "hex": "#d9ba73", 1248 | "rgb": { 1249 | "r": 217, 1250 | "g": 186, 1251 | "b": 115 1252 | }, 1253 | "hsl": { 1254 | "h": 41.764705882352935, 1255 | "s": 0.5730337078651685, 1256 | "l": 0.6509803921568628 1257 | }, 1258 | "code": 11 1259 | } 1260 | }, 1261 | "blue": { 1262 | "name": "Blue", 1263 | "order": 4, 1264 | "normal": { 1265 | "name": "Blue", 1266 | "hex": "#8caaee", 1267 | "rgb": { 1268 | "r": 140, 1269 | "g": 170, 1270 | "b": 238 1271 | }, 1272 | "hsl": { 1273 | "h": 221.6326530612245, 1274 | "s": 0.7424242424242424, 1275 | "l": 0.7411764705882353 1276 | }, 1277 | "code": 4 1278 | }, 1279 | "bright": { 1280 | "name": "Bright Blue", 1281 | "hex": "#7b9ef0", 1282 | "rgb": { 1283 | "r": 123, 1284 | "g": 158, 1285 | "b": 240 1286 | }, 1287 | "hsl": { 1288 | "h": 222.05128205128207, 1289 | "s": 0.7959183673469388, 1290 | "l": 0.711764705882353 1291 | }, 1292 | "code": 12 1293 | } 1294 | }, 1295 | "magenta": { 1296 | "name": "Magenta", 1297 | "order": 5, 1298 | "normal": { 1299 | "name": "Magenta", 1300 | "hex": "#f4b8e4", 1301 | "rgb": { 1302 | "r": 244, 1303 | "g": 184, 1304 | "b": 228 1305 | }, 1306 | "hsl": { 1307 | "h": 316, 1308 | "s": 0.7317073170731713, 1309 | "l": 0.8392156862745098 1310 | }, 1311 | "code": 5 1312 | }, 1313 | "bright": { 1314 | "name": "Bright Magenta", 1315 | "hex": "#f2a4db", 1316 | "rgb": { 1317 | "r": 242, 1318 | "g": 164, 1319 | "b": 219 1320 | }, 1321 | "hsl": { 1322 | "h": 317.6923076923077, 1323 | "s": 0.7499999999999998, 1324 | "l": 0.7960784313725491 1325 | }, 1326 | "code": 13 1327 | } 1328 | }, 1329 | "cyan": { 1330 | "name": "Cyan", 1331 | "order": 6, 1332 | "normal": { 1333 | "name": "Cyan", 1334 | "hex": "#81c8be", 1335 | "rgb": { 1336 | "r": 129, 1337 | "g": 200, 1338 | "b": 190 1339 | }, 1340 | "hsl": { 1341 | "h": 171.5492957746479, 1342 | "s": 0.3922651933701657, 1343 | "l": 0.6450980392156862 1344 | }, 1345 | "code": 6 1346 | }, 1347 | "bright": { 1348 | "name": "Bright Cyan", 1349 | "hex": "#5abfb5", 1350 | "rgb": { 1351 | "r": 90, 1352 | "g": 191, 1353 | "b": 181 1354 | }, 1355 | "hsl": { 1356 | "h": 174.05940594059405, 1357 | "s": 0.44104803493449785, 1358 | "l": 0.5509803921568628 1359 | }, 1360 | "code": 14 1361 | } 1362 | }, 1363 | "white": { 1364 | "name": "White", 1365 | "order": 7, 1366 | "normal": { 1367 | "name": "White", 1368 | "hex": "#a5adce", 1369 | "rgb": { 1370 | "r": 165, 1371 | "g": 173, 1372 | "b": 206 1373 | }, 1374 | "hsl": { 1375 | "h": 228.29268292682926, 1376 | "s": 0.2949640287769784, 1377 | "l": 0.7274509803921569 1378 | }, 1379 | "code": 7 1380 | }, 1381 | "bright": { 1382 | "name": "Bright White", 1383 | "hex": "#b5bfe2", 1384 | "rgb": { 1385 | "r": 181, 1386 | "g": 191, 1387 | "b": 226 1388 | }, 1389 | "hsl": { 1390 | "h": 226.66666666666669, 1391 | "s": 0.43689320388349495, 1392 | "l": 0.7980392156862746 1393 | }, 1394 | "code": 15 1395 | } 1396 | } 1397 | } 1398 | }, 1399 | "macchiato": { 1400 | "name": "Macchiato", 1401 | "emoji": "🌺", 1402 | "order": 2, 1403 | "dark": true, 1404 | "colors": { 1405 | "rosewater": { 1406 | "name": "Rosewater", 1407 | "order": 0, 1408 | "hex": "#f4dbd6", 1409 | "rgb": { 1410 | "r": 244, 1411 | "g": 219, 1412 | "b": 214 1413 | }, 1414 | "hsl": { 1415 | "h": 9.999999999999963, 1416 | "s": 0.5769230769230775, 1417 | "l": 0.8980392156862745 1418 | }, 1419 | "accent": true 1420 | }, 1421 | "flamingo": { 1422 | "name": "Flamingo", 1423 | "order": 1, 1424 | "hex": "#f0c6c6", 1425 | "rgb": { 1426 | "r": 240, 1427 | "g": 198, 1428 | "b": 198 1429 | }, 1430 | "hsl": { 1431 | "h": 0, 1432 | "s": 0.5833333333333333, 1433 | "l": 0.8588235294117648 1434 | }, 1435 | "accent": true 1436 | }, 1437 | "pink": { 1438 | "name": "Pink", 1439 | "order": 2, 1440 | "hex": "#f5bde6", 1441 | "rgb": { 1442 | "r": 245, 1443 | "g": 189, 1444 | "b": 230 1445 | }, 1446 | "hsl": { 1447 | "h": 316.0714285714286, 1448 | "s": 0.7368421052631583, 1449 | "l": 0.8509803921568628 1450 | }, 1451 | "accent": true 1452 | }, 1453 | "mauve": { 1454 | "name": "Mauve", 1455 | "order": 3, 1456 | "hex": "#c6a0f6", 1457 | "rgb": { 1458 | "r": 198, 1459 | "g": 160, 1460 | "b": 246 1461 | }, 1462 | "hsl": { 1463 | "h": 266.51162790697674, 1464 | "s": 0.8269230769230772, 1465 | "l": 0.7960784313725491 1466 | }, 1467 | "accent": true 1468 | }, 1469 | "red": { 1470 | "name": "Red", 1471 | "order": 4, 1472 | "hex": "#ed8796", 1473 | "rgb": { 1474 | "r": 237, 1475 | "g": 135, 1476 | "b": 150 1477 | }, 1478 | "hsl": { 1479 | "h": 351.1764705882353, 1480 | "s": 0.7391304347826088, 1481 | "l": 0.7294117647058824 1482 | }, 1483 | "accent": true 1484 | }, 1485 | "maroon": { 1486 | "name": "Maroon", 1487 | "order": 5, 1488 | "hex": "#ee99a0", 1489 | "rgb": { 1490 | "r": 238, 1491 | "g": 153, 1492 | "b": 160 1493 | }, 1494 | "hsl": { 1495 | "h": 355.05882352941177, 1496 | "s": 0.7142857142857143, 1497 | "l": 0.7666666666666666 1498 | }, 1499 | "accent": true 1500 | }, 1501 | "peach": { 1502 | "name": "Peach", 1503 | "order": 6, 1504 | "hex": "#f5a97f", 1505 | "rgb": { 1506 | "r": 245, 1507 | "g": 169, 1508 | "b": 127 1509 | }, 1510 | "hsl": { 1511 | "h": 21.355932203389827, 1512 | "s": 0.8550724637681162, 1513 | "l": 0.7294117647058824 1514 | }, 1515 | "accent": true 1516 | }, 1517 | "yellow": { 1518 | "name": "Yellow", 1519 | "order": 7, 1520 | "hex": "#eed49f", 1521 | "rgb": { 1522 | "r": 238, 1523 | "g": 212, 1524 | "b": 159 1525 | }, 1526 | "hsl": { 1527 | "h": 40.253164556962034, 1528 | "s": 0.6991150442477877, 1529 | "l": 0.7784313725490196 1530 | }, 1531 | "accent": true 1532 | }, 1533 | "green": { 1534 | "name": "Green", 1535 | "order": 8, 1536 | "hex": "#a6da95", 1537 | "rgb": { 1538 | "r": 166, 1539 | "g": 218, 1540 | "b": 149 1541 | }, 1542 | "hsl": { 1543 | "h": 105.21739130434783, 1544 | "s": 0.4825174825174825, 1545 | "l": 0.7196078431372549 1546 | }, 1547 | "accent": true 1548 | }, 1549 | "teal": { 1550 | "name": "Teal", 1551 | "order": 9, 1552 | "hex": "#8bd5ca", 1553 | "rgb": { 1554 | "r": 139, 1555 | "g": 213, 1556 | "b": 202 1557 | }, 1558 | "hsl": { 1559 | "h": 171.08108108108107, 1560 | "s": 0.46835443037974706, 1561 | "l": 0.6901960784313725 1562 | }, 1563 | "accent": true 1564 | }, 1565 | "sky": { 1566 | "name": "Sky", 1567 | "order": 10, 1568 | "hex": "#91d7e3", 1569 | "rgb": { 1570 | "r": 145, 1571 | "g": 215, 1572 | "b": 227 1573 | }, 1574 | "hsl": { 1575 | "h": 188.78048780487802, 1576 | "s": 0.5942028985507245, 1577 | "l": 0.7294117647058823 1578 | }, 1579 | "accent": true 1580 | }, 1581 | "sapphire": { 1582 | "name": "Sapphire", 1583 | "order": 11, 1584 | "hex": "#7dc4e4", 1585 | "rgb": { 1586 | "r": 125, 1587 | "g": 196, 1588 | "b": 228 1589 | }, 1590 | "hsl": { 1591 | "h": 198.64077669902912, 1592 | "s": 0.6560509554140128, 1593 | "l": 0.692156862745098 1594 | }, 1595 | "accent": true 1596 | }, 1597 | "blue": { 1598 | "name": "Blue", 1599 | "order": 12, 1600 | "hex": "#8aadf4", 1601 | "rgb": { 1602 | "r": 138, 1603 | "g": 173, 1604 | "b": 244 1605 | }, 1606 | "hsl": { 1607 | "h": 220.188679245283, 1608 | "s": 0.8281250000000003, 1609 | "l": 0.7490196078431373 1610 | }, 1611 | "accent": true 1612 | }, 1613 | "lavender": { 1614 | "name": "Lavender", 1615 | "order": 13, 1616 | "hex": "#b7bdf8", 1617 | "rgb": { 1618 | "r": 183, 1619 | "g": 189, 1620 | "b": 248 1621 | }, 1622 | "hsl": { 1623 | "h": 234.46153846153848, 1624 | "s": 0.8227848101265824, 1625 | "l": 0.8450980392156863 1626 | }, 1627 | "accent": true 1628 | }, 1629 | "text": { 1630 | "name": "Text", 1631 | "order": 14, 1632 | "hex": "#cad3f5", 1633 | "rgb": { 1634 | "r": 202, 1635 | "g": 211, 1636 | "b": 245 1637 | }, 1638 | "hsl": { 1639 | "h": 227.4418604651163, 1640 | "s": 0.6825396825396831, 1641 | "l": 0.8764705882352941 1642 | }, 1643 | "accent": false 1644 | }, 1645 | "subtext1": { 1646 | "name": "Subtext 1", 1647 | "order": 15, 1648 | "hex": "#b8c0e0", 1649 | "rgb": { 1650 | "r": 184, 1651 | "g": 192, 1652 | "b": 224 1653 | }, 1654 | "hsl": { 1655 | "h": 228, 1656 | "s": 0.39215686274509803, 1657 | "l": 0.8 1658 | }, 1659 | "accent": false 1660 | }, 1661 | "subtext0": { 1662 | "name": "Subtext 0", 1663 | "order": 16, 1664 | "hex": "#a5adcb", 1665 | "rgb": { 1666 | "r": 165, 1667 | "g": 173, 1668 | "b": 203 1669 | }, 1670 | "hsl": { 1671 | "h": 227.36842105263156, 1672 | "s": 0.2676056338028167, 1673 | "l": 0.7215686274509804 1674 | }, 1675 | "accent": false 1676 | }, 1677 | "overlay2": { 1678 | "name": "Overlay 2", 1679 | "order": 17, 1680 | "hex": "#939ab7", 1681 | "rgb": { 1682 | "r": 147, 1683 | "g": 154, 1684 | "b": 183 1685 | }, 1686 | "hsl": { 1687 | "h": 228.33333333333331, 1688 | "s": 0.2000000000000001, 1689 | "l": 0.6470588235294117 1690 | }, 1691 | "accent": false 1692 | }, 1693 | "overlay1": { 1694 | "name": "Overlay 1", 1695 | "order": 18, 1696 | "hex": "#8087a2", 1697 | "rgb": { 1698 | "r": 128, 1699 | "g": 135, 1700 | "b": 162 1701 | }, 1702 | "hsl": { 1703 | "h": 227.6470588235294, 1704 | "s": 0.1545454545454545, 1705 | "l": 0.5686274509803921 1706 | }, 1707 | "accent": false 1708 | }, 1709 | "overlay0": { 1710 | "name": "Overlay 0", 1711 | "order": 19, 1712 | "hex": "#6e738d", 1713 | "rgb": { 1714 | "r": 110, 1715 | "g": 115, 1716 | "b": 141 1717 | }, 1718 | "hsl": { 1719 | "h": 230.32258064516128, 1720 | "s": 0.12350597609561753, 1721 | "l": 0.49215686274509807 1722 | }, 1723 | "accent": false 1724 | }, 1725 | "surface2": { 1726 | "name": "Surface 2", 1727 | "order": 20, 1728 | "hex": "#5b6078", 1729 | "rgb": { 1730 | "r": 91, 1731 | "g": 96, 1732 | "b": 120 1733 | }, 1734 | "hsl": { 1735 | "h": 229.65517241379308, 1736 | "s": 0.13744075829383887, 1737 | "l": 0.4137254901960784 1738 | }, 1739 | "accent": false 1740 | }, 1741 | "surface1": { 1742 | "name": "Surface 1", 1743 | "order": 21, 1744 | "hex": "#494d64", 1745 | "rgb": { 1746 | "r": 73, 1747 | "g": 77, 1748 | "b": 100 1749 | }, 1750 | "hsl": { 1751 | "h": 231.11111111111114, 1752 | "s": 0.15606936416184972, 1753 | "l": 0.3392156862745098 1754 | }, 1755 | "accent": false 1756 | }, 1757 | "surface0": { 1758 | "name": "Surface 0", 1759 | "order": 22, 1760 | "hex": "#363a4f", 1761 | "rgb": { 1762 | "r": 54, 1763 | "g": 58, 1764 | "b": 79 1765 | }, 1766 | "hsl": { 1767 | "h": 230.4, 1768 | "s": 0.1879699248120301, 1769 | "l": 0.2607843137254902 1770 | }, 1771 | "accent": false 1772 | }, 1773 | "base": { 1774 | "name": "Base", 1775 | "order": 23, 1776 | "hex": "#24273a", 1777 | "rgb": { 1778 | "r": 36, 1779 | "g": 39, 1780 | "b": 58 1781 | }, 1782 | "hsl": { 1783 | "h": 231.8181818181818, 1784 | "s": 0.23404255319148934, 1785 | "l": 0.1843137254901961 1786 | }, 1787 | "accent": false 1788 | }, 1789 | "mantle": { 1790 | "name": "Mantle", 1791 | "order": 24, 1792 | "hex": "#1e2030", 1793 | "rgb": { 1794 | "r": 30, 1795 | "g": 32, 1796 | "b": 48 1797 | }, 1798 | "hsl": { 1799 | "h": 233.33333333333334, 1800 | "s": 0.23076923076923075, 1801 | "l": 0.15294117647058825 1802 | }, 1803 | "accent": false 1804 | }, 1805 | "crust": { 1806 | "name": "Crust", 1807 | "order": 25, 1808 | "hex": "#181926", 1809 | "rgb": { 1810 | "r": 24, 1811 | "g": 25, 1812 | "b": 38 1813 | }, 1814 | "hsl": { 1815 | "h": 235.71428571428572, 1816 | "s": 0.22580645161290322, 1817 | "l": 0.12156862745098039 1818 | }, 1819 | "accent": false 1820 | } 1821 | }, 1822 | "ansiColors": { 1823 | "black": { 1824 | "name": "Black", 1825 | "order": 0, 1826 | "normal": { 1827 | "name": "Black", 1828 | "hex": "#494d64", 1829 | "rgb": { 1830 | "r": 73, 1831 | "g": 77, 1832 | "b": 100 1833 | }, 1834 | "hsl": { 1835 | "h": 231.11111111111114, 1836 | "s": 0.15606936416184972, 1837 | "l": 0.3392156862745098 1838 | }, 1839 | "code": 0 1840 | }, 1841 | "bright": { 1842 | "name": "Bright Black", 1843 | "hex": "#5b6078", 1844 | "rgb": { 1845 | "r": 91, 1846 | "g": 96, 1847 | "b": 120 1848 | }, 1849 | "hsl": { 1850 | "h": 229.65517241379308, 1851 | "s": 0.13744075829383887, 1852 | "l": 0.4137254901960784 1853 | }, 1854 | "code": 8 1855 | } 1856 | }, 1857 | "red": { 1858 | "name": "Red", 1859 | "order": 1, 1860 | "normal": { 1861 | "name": "Red", 1862 | "hex": "#ed8796", 1863 | "rgb": { 1864 | "r": 237, 1865 | "g": 135, 1866 | "b": 150 1867 | }, 1868 | "hsl": { 1869 | "h": 351.1764705882353, 1870 | "s": 0.7391304347826088, 1871 | "l": 0.7294117647058824 1872 | }, 1873 | "code": 1 1874 | }, 1875 | "bright": { 1876 | "name": "Bright Red", 1877 | "hex": "#ec7486", 1878 | "rgb": { 1879 | "r": 236, 1880 | "g": 116, 1881 | "b": 134 1882 | }, 1883 | "hsl": { 1884 | "h": 351, 1885 | "s": 0.759493670886076, 1886 | "l": 0.6901960784313725 1887 | }, 1888 | "code": 9 1889 | } 1890 | }, 1891 | "green": { 1892 | "name": "Green", 1893 | "order": 2, 1894 | "normal": { 1895 | "name": "Green", 1896 | "hex": "#a6da95", 1897 | "rgb": { 1898 | "r": 166, 1899 | "g": 218, 1900 | "b": 149 1901 | }, 1902 | "hsl": { 1903 | "h": 105.21739130434783, 1904 | "s": 0.4825174825174825, 1905 | "l": 0.7196078431372549 1906 | }, 1907 | "code": 2 1908 | }, 1909 | "bright": { 1910 | "name": "Bright Green", 1911 | "hex": "#8ccf7f", 1912 | "rgb": { 1913 | "r": 140, 1914 | "g": 207, 1915 | "b": 127 1916 | }, 1917 | "hsl": { 1918 | "h": 110.24999999999999, 1919 | "s": 0.45454545454545453, 1920 | "l": 0.6549019607843137 1921 | }, 1922 | "code": 10 1923 | } 1924 | }, 1925 | "yellow": { 1926 | "name": "Yellow", 1927 | "order": 3, 1928 | "normal": { 1929 | "name": "Yellow", 1930 | "hex": "#eed49f", 1931 | "rgb": { 1932 | "r": 238, 1933 | "g": 212, 1934 | "b": 159 1935 | }, 1936 | "hsl": { 1937 | "h": 40.253164556962034, 1938 | "s": 0.6991150442477877, 1939 | "l": 0.7784313725490196 1940 | }, 1941 | "code": 3 1942 | }, 1943 | "bright": { 1944 | "name": "Bright Yellow", 1945 | "hex": "#e1c682", 1946 | "rgb": { 1947 | "r": 225, 1948 | "g": 198, 1949 | "b": 130 1950 | }, 1951 | "hsl": { 1952 | "h": 42.94736842105264, 1953 | "s": 0.6129032258064515, 1954 | "l": 0.696078431372549 1955 | }, 1956 | "code": 11 1957 | } 1958 | }, 1959 | "blue": { 1960 | "name": "Blue", 1961 | "order": 4, 1962 | "normal": { 1963 | "name": "Blue", 1964 | "hex": "#8aadf4", 1965 | "rgb": { 1966 | "r": 138, 1967 | "g": 173, 1968 | "b": 244 1969 | }, 1970 | "hsl": { 1971 | "h": 220.188679245283, 1972 | "s": 0.8281250000000003, 1973 | "l": 0.7490196078431373 1974 | }, 1975 | "code": 4 1976 | }, 1977 | "bright": { 1978 | "name": "Bright Blue", 1979 | "hex": "#78a1f6", 1980 | "rgb": { 1981 | "r": 120, 1982 | "g": 161, 1983 | "b": 246 1984 | }, 1985 | "hsl": { 1986 | "h": 220.47619047619048, 1987 | "s": 0.8750000000000002, 1988 | "l": 0.7176470588235294 1989 | }, 1990 | "code": 12 1991 | } 1992 | }, 1993 | "magenta": { 1994 | "name": "Magenta", 1995 | "order": 5, 1996 | "normal": { 1997 | "name": "Magenta", 1998 | "hex": "#f5bde6", 1999 | "rgb": { 2000 | "r": 245, 2001 | "g": 189, 2002 | "b": 230 2003 | }, 2004 | "hsl": { 2005 | "h": 316.0714285714286, 2006 | "s": 0.7368421052631583, 2007 | "l": 0.8509803921568628 2008 | }, 2009 | "code": 5 2010 | }, 2011 | "bright": { 2012 | "name": "Bright Magenta", 2013 | "hex": "#f2a9dd", 2014 | "rgb": { 2015 | "r": 242, 2016 | "g": 169, 2017 | "b": 221 2018 | }, 2019 | "hsl": { 2020 | "h": 317.26027397260276, 2021 | "s": 0.7373737373737372, 2022 | "l": 0.8058823529411765 2023 | }, 2024 | "code": 13 2025 | } 2026 | }, 2027 | "cyan": { 2028 | "name": "Cyan", 2029 | "order": 6, 2030 | "normal": { 2031 | "name": "Cyan", 2032 | "hex": "#8bd5ca", 2033 | "rgb": { 2034 | "r": 139, 2035 | "g": 213, 2036 | "b": 202 2037 | }, 2038 | "hsl": { 2039 | "h": 171.08108108108107, 2040 | "s": 0.46835443037974706, 2041 | "l": 0.6901960784313725 2042 | }, 2043 | "code": 6 2044 | }, 2045 | "bright": { 2046 | "name": "Bright Cyan", 2047 | "hex": "#63cbc0", 2048 | "rgb": { 2049 | "r": 99, 2050 | "g": 203, 2051 | "b": 192 2052 | }, 2053 | "hsl": { 2054 | "h": 173.65384615384616, 2055 | "s": 0.4999999999999998, 2056 | "l": 0.592156862745098 2057 | }, 2058 | "code": 14 2059 | } 2060 | }, 2061 | "white": { 2062 | "name": "White", 2063 | "order": 7, 2064 | "normal": { 2065 | "name": "White", 2066 | "hex": "#a5adcb", 2067 | "rgb": { 2068 | "r": 165, 2069 | "g": 173, 2070 | "b": 203 2071 | }, 2072 | "hsl": { 2073 | "h": 227.36842105263156, 2074 | "s": 0.2676056338028167, 2075 | "l": 0.7215686274509804 2076 | }, 2077 | "code": 7 2078 | }, 2079 | "bright": { 2080 | "name": "Bright White", 2081 | "hex": "#b8c0e0", 2082 | "rgb": { 2083 | "r": 184, 2084 | "g": 192, 2085 | "b": 224 2086 | }, 2087 | "hsl": { 2088 | "h": 228, 2089 | "s": 0.39215686274509803, 2090 | "l": 0.8 2091 | }, 2092 | "code": 15 2093 | } 2094 | } 2095 | } 2096 | }, 2097 | "mocha": { 2098 | "name": "Mocha", 2099 | "emoji": "🌿", 2100 | "order": 3, 2101 | "dark": true, 2102 | "colors": { 2103 | "rosewater": { 2104 | "name": "Rosewater", 2105 | "order": 0, 2106 | "hex": "#f5e0dc", 2107 | "rgb": { 2108 | "r": 245, 2109 | "g": 224, 2110 | "b": 220 2111 | }, 2112 | "hsl": { 2113 | "h": 9.599999999999968, 2114 | "s": 0.555555555555556, 2115 | "l": 0.911764705882353 2116 | }, 2117 | "accent": true 2118 | }, 2119 | "flamingo": { 2120 | "name": "Flamingo", 2121 | "order": 1, 2122 | "hex": "#f2cdcd", 2123 | "rgb": { 2124 | "r": 242, 2125 | "g": 205, 2126 | "b": 205 2127 | }, 2128 | "hsl": { 2129 | "h": 0, 2130 | "s": 0.587301587301587, 2131 | "l": 0.8764705882352941 2132 | }, 2133 | "accent": true 2134 | }, 2135 | "pink": { 2136 | "name": "Pink", 2137 | "order": 2, 2138 | "hex": "#f5c2e7", 2139 | "rgb": { 2140 | "r": 245, 2141 | "g": 194, 2142 | "b": 231 2143 | }, 2144 | "hsl": { 2145 | "h": 316.4705882352941, 2146 | "s": 0.7183098591549301, 2147 | "l": 0.8607843137254902 2148 | }, 2149 | "accent": true 2150 | }, 2151 | "mauve": { 2152 | "name": "Mauve", 2153 | "order": 3, 2154 | "hex": "#cba6f7", 2155 | "rgb": { 2156 | "r": 203, 2157 | "g": 166, 2158 | "b": 247 2159 | }, 2160 | "hsl": { 2161 | "h": 267.4074074074074, 2162 | "s": 0.8350515463917528, 2163 | "l": 0.8098039215686275 2164 | }, 2165 | "accent": true 2166 | }, 2167 | "red": { 2168 | "name": "Red", 2169 | "order": 4, 2170 | "hex": "#f38ba8", 2171 | "rgb": { 2172 | "r": 243, 2173 | "g": 139, 2174 | "b": 168 2175 | }, 2176 | "hsl": { 2177 | "h": 343.2692307692308, 2178 | "s": 0.8124999999999998, 2179 | "l": 0.7490196078431373 2180 | }, 2181 | "accent": true 2182 | }, 2183 | "maroon": { 2184 | "name": "Maroon", 2185 | "order": 5, 2186 | "hex": "#eba0ac", 2187 | "rgb": { 2188 | "r": 235, 2189 | "g": 160, 2190 | "b": 172 2191 | }, 2192 | "hsl": { 2193 | "h": 350.4, 2194 | "s": 0.6521739130434779, 2195 | "l": 0.7745098039215685 2196 | }, 2197 | "accent": true 2198 | }, 2199 | "peach": { 2200 | "name": "Peach", 2201 | "order": 6, 2202 | "hex": "#fab387", 2203 | "rgb": { 2204 | "r": 250, 2205 | "g": 179, 2206 | "b": 135 2207 | }, 2208 | "hsl": { 2209 | "h": 22.95652173913043, 2210 | "s": 0.92, 2211 | "l": 0.7549019607843137 2212 | }, 2213 | "accent": true 2214 | }, 2215 | "yellow": { 2216 | "name": "Yellow", 2217 | "order": 7, 2218 | "hex": "#f9e2af", 2219 | "rgb": { 2220 | "r": 249, 2221 | "g": 226, 2222 | "b": 175 2223 | }, 2224 | "hsl": { 2225 | "h": 41.35135135135135, 2226 | "s": 0.8604651162790699, 2227 | "l": 0.8313725490196078 2228 | }, 2229 | "accent": true 2230 | }, 2231 | "green": { 2232 | "name": "Green", 2233 | "order": 8, 2234 | "hex": "#a6e3a1", 2235 | "rgb": { 2236 | "r": 166, 2237 | "g": 227, 2238 | "b": 161 2239 | }, 2240 | "hsl": { 2241 | "h": 115.45454545454544, 2242 | "s": 0.5409836065573769, 2243 | "l": 0.7607843137254902 2244 | }, 2245 | "accent": true 2246 | }, 2247 | "teal": { 2248 | "name": "Teal", 2249 | "order": 9, 2250 | "hex": "#94e2d5", 2251 | "rgb": { 2252 | "r": 148, 2253 | "g": 226, 2254 | "b": 213 2255 | }, 2256 | "hsl": { 2257 | "h": 170.00000000000003, 2258 | "s": 0.5735294117647057, 2259 | "l": 0.7333333333333334 2260 | }, 2261 | "accent": true 2262 | }, 2263 | "sky": { 2264 | "name": "Sky", 2265 | "order": 10, 2266 | "hex": "#89dceb", 2267 | "rgb": { 2268 | "r": 137, 2269 | "g": 220, 2270 | "b": 235 2271 | }, 2272 | "hsl": { 2273 | "h": 189.18367346938774, 2274 | "s": 0.7101449275362316, 2275 | "l": 0.7294117647058823 2276 | }, 2277 | "accent": true 2278 | }, 2279 | "sapphire": { 2280 | "name": "Sapphire", 2281 | "order": 11, 2282 | "hex": "#74c7ec", 2283 | "rgb": { 2284 | "r": 116, 2285 | "g": 199, 2286 | "b": 236 2287 | }, 2288 | "hsl": { 2289 | "h": 198.5, 2290 | "s": 0.759493670886076, 2291 | "l": 0.6901960784313725 2292 | }, 2293 | "accent": true 2294 | }, 2295 | "blue": { 2296 | "name": "Blue", 2297 | "order": 12, 2298 | "hex": "#89b4fa", 2299 | "rgb": { 2300 | "r": 137, 2301 | "g": 180, 2302 | "b": 250 2303 | }, 2304 | "hsl": { 2305 | "h": 217.1681415929203, 2306 | "s": 0.9186991869918699, 2307 | "l": 0.7588235294117647 2308 | }, 2309 | "accent": true 2310 | }, 2311 | "lavender": { 2312 | "name": "Lavender", 2313 | "order": 13, 2314 | "hex": "#b4befe", 2315 | "rgb": { 2316 | "r": 180, 2317 | "g": 190, 2318 | "b": 254 2319 | }, 2320 | "hsl": { 2321 | "h": 231.89189189189187, 2322 | "s": 0.9736842105263159, 2323 | "l": 0.8509803921568628 2324 | }, 2325 | "accent": true 2326 | }, 2327 | "text": { 2328 | "name": "Text", 2329 | "order": 14, 2330 | "hex": "#cdd6f4", 2331 | "rgb": { 2332 | "r": 205, 2333 | "g": 214, 2334 | "b": 244 2335 | }, 2336 | "hsl": { 2337 | "h": 226.15384615384616, 2338 | "s": 0.6393442622950825, 2339 | "l": 0.8803921568627451 2340 | }, 2341 | "accent": false 2342 | }, 2343 | "subtext1": { 2344 | "name": "Subtext 1", 2345 | "order": 15, 2346 | "hex": "#bac2de", 2347 | "rgb": { 2348 | "r": 186, 2349 | "g": 194, 2350 | "b": 222 2351 | }, 2352 | "hsl": { 2353 | "h": 226.66666666666669, 2354 | "s": 0.35294117647058837, 2355 | "l": 0.8 2356 | }, 2357 | "accent": false 2358 | }, 2359 | "subtext0": { 2360 | "name": "Subtext 0", 2361 | "order": 16, 2362 | "hex": "#a6adc8", 2363 | "rgb": { 2364 | "r": 166, 2365 | "g": 173, 2366 | "b": 200 2367 | }, 2368 | "hsl": { 2369 | "h": 227.6470588235294, 2370 | "s": 0.23611111111111102, 2371 | "l": 0.7176470588235294 2372 | }, 2373 | "accent": false 2374 | }, 2375 | "overlay2": { 2376 | "name": "Overlay 2", 2377 | "order": 17, 2378 | "hex": "#9399b2", 2379 | "rgb": { 2380 | "r": 147, 2381 | "g": 153, 2382 | "b": 178 2383 | }, 2384 | "hsl": { 2385 | "h": 228.38709677419354, 2386 | "s": 0.16756756756756758, 2387 | "l": 0.6372549019607843 2388 | }, 2389 | "accent": false 2390 | }, 2391 | "overlay1": { 2392 | "name": "Overlay 1", 2393 | "order": 18, 2394 | "hex": "#7f849c", 2395 | "rgb": { 2396 | "r": 127, 2397 | "g": 132, 2398 | "b": 156 2399 | }, 2400 | "hsl": { 2401 | "h": 229.65517241379308, 2402 | "s": 0.12775330396475776, 2403 | "l": 0.5549019607843138 2404 | }, 2405 | "accent": false 2406 | }, 2407 | "overlay0": { 2408 | "name": "Overlay 0", 2409 | "order": 19, 2410 | "hex": "#6c7086", 2411 | "rgb": { 2412 | "r": 108, 2413 | "g": 112, 2414 | "b": 134 2415 | }, 2416 | "hsl": { 2417 | "h": 230.7692307692308, 2418 | "s": 0.10743801652892565, 2419 | "l": 0.4745098039215686 2420 | }, 2421 | "accent": false 2422 | }, 2423 | "surface2": { 2424 | "name": "Surface 2", 2425 | "order": 20, 2426 | "hex": "#585b70", 2427 | "rgb": { 2428 | "r": 88, 2429 | "g": 91, 2430 | "b": 112 2431 | }, 2432 | "hsl": { 2433 | "h": 232.5, 2434 | "s": 0.12, 2435 | "l": 0.39215686274509803 2436 | }, 2437 | "accent": false 2438 | }, 2439 | "surface1": { 2440 | "name": "Surface 1", 2441 | "order": 21, 2442 | "hex": "#45475a", 2443 | "rgb": { 2444 | "r": 69, 2445 | "g": 71, 2446 | "b": 90 2447 | }, 2448 | "hsl": { 2449 | "h": 234.2857142857143, 2450 | "s": 0.13207547169811326, 2451 | "l": 0.31176470588235294 2452 | }, 2453 | "accent": false 2454 | }, 2455 | "surface0": { 2456 | "name": "Surface 0", 2457 | "order": 22, 2458 | "hex": "#313244", 2459 | "rgb": { 2460 | "r": 49, 2461 | "g": 50, 2462 | "b": 68 2463 | }, 2464 | "hsl": { 2465 | "h": 236.84210526315792, 2466 | "s": 0.16239316239316234, 2467 | "l": 0.22941176470588237 2468 | }, 2469 | "accent": false 2470 | }, 2471 | "base": { 2472 | "name": "Base", 2473 | "order": 23, 2474 | "hex": "#1e1e2e", 2475 | "rgb": { 2476 | "r": 30, 2477 | "g": 30, 2478 | "b": 46 2479 | }, 2480 | "hsl": { 2481 | "h": 240, 2482 | "s": 0.21052631578947367, 2483 | "l": 0.14901960784313725 2484 | }, 2485 | "accent": false 2486 | }, 2487 | "mantle": { 2488 | "name": "Mantle", 2489 | "order": 24, 2490 | "hex": "#181825", 2491 | "rgb": { 2492 | "r": 24, 2493 | "g": 24, 2494 | "b": 37 2495 | }, 2496 | "hsl": { 2497 | "h": 240, 2498 | "s": 0.2131147540983607, 2499 | "l": 0.11960784313725491 2500 | }, 2501 | "accent": false 2502 | }, 2503 | "crust": { 2504 | "name": "Crust", 2505 | "order": 25, 2506 | "hex": "#11111b", 2507 | "rgb": { 2508 | "r": 17, 2509 | "g": 17, 2510 | "b": 27 2511 | }, 2512 | "hsl": { 2513 | "h": 240, 2514 | "s": 0.22727272727272727, 2515 | "l": 0.08627450980392157 2516 | }, 2517 | "accent": false 2518 | } 2519 | }, 2520 | "ansiColors": { 2521 | "black": { 2522 | "name": "Black", 2523 | "order": 0, 2524 | "normal": { 2525 | "name": "Black", 2526 | "hex": "#45475a", 2527 | "rgb": { 2528 | "r": 69, 2529 | "g": 71, 2530 | "b": 90 2531 | }, 2532 | "hsl": { 2533 | "h": 234.2857142857143, 2534 | "s": 0.13207547169811326, 2535 | "l": 0.31176470588235294 2536 | }, 2537 | "code": 0 2538 | }, 2539 | "bright": { 2540 | "name": "Bright Black", 2541 | "hex": "#585b70", 2542 | "rgb": { 2543 | "r": 88, 2544 | "g": 91, 2545 | "b": 112 2546 | }, 2547 | "hsl": { 2548 | "h": 232.5, 2549 | "s": 0.12, 2550 | "l": 0.39215686274509803 2551 | }, 2552 | "code": 8 2553 | } 2554 | }, 2555 | "red": { 2556 | "name": "Red", 2557 | "order": 1, 2558 | "normal": { 2559 | "name": "Red", 2560 | "hex": "#f38ba8", 2561 | "rgb": { 2562 | "r": 243, 2563 | "g": 139, 2564 | "b": 168 2565 | }, 2566 | "hsl": { 2567 | "h": 343.2692307692308, 2568 | "s": 0.8124999999999998, 2569 | "l": 0.7490196078431373 2570 | }, 2571 | "code": 1 2572 | }, 2573 | "bright": { 2574 | "name": "Bright Red", 2575 | "hex": "#f37799", 2576 | "rgb": { 2577 | "r": 243, 2578 | "g": 119, 2579 | "b": 153 2580 | }, 2581 | "hsl": { 2582 | "h": 343.54838709677415, 2583 | "s": 0.8378378378378376, 2584 | "l": 0.7098039215686274 2585 | }, 2586 | "code": 9 2587 | } 2588 | }, 2589 | "green": { 2590 | "name": "Green", 2591 | "order": 2, 2592 | "normal": { 2593 | "name": "Green", 2594 | "hex": "#a6e3a1", 2595 | "rgb": { 2596 | "r": 166, 2597 | "g": 227, 2598 | "b": 161 2599 | }, 2600 | "hsl": { 2601 | "h": 115.45454545454544, 2602 | "s": 0.5409836065573769, 2603 | "l": 0.7607843137254902 2604 | }, 2605 | "code": 2 2606 | }, 2607 | "bright": { 2608 | "name": "Bright Green", 2609 | "hex": "#89d88b", 2610 | "rgb": { 2611 | "r": 137, 2612 | "g": 216, 2613 | "b": 139 2614 | }, 2615 | "hsl": { 2616 | "h": 121.51898734177213, 2617 | "s": 0.5031847133757963, 2618 | "l": 0.692156862745098 2619 | }, 2620 | "code": 10 2621 | } 2622 | }, 2623 | "yellow": { 2624 | "name": "Yellow", 2625 | "order": 3, 2626 | "normal": { 2627 | "name": "Yellow", 2628 | "hex": "#f9e2af", 2629 | "rgb": { 2630 | "r": 249, 2631 | "g": 226, 2632 | "b": 175 2633 | }, 2634 | "hsl": { 2635 | "h": 41.35135135135135, 2636 | "s": 0.8604651162790699, 2637 | "l": 0.8313725490196078 2638 | }, 2639 | "code": 3 2640 | }, 2641 | "bright": { 2642 | "name": "Bright Yellow", 2643 | "hex": "#ebd391", 2644 | "rgb": { 2645 | "r": 235, 2646 | "g": 211, 2647 | "b": 145 2648 | }, 2649 | "hsl": { 2650 | "h": 44, 2651 | "s": 0.692307692307692, 2652 | "l": 0.7450980392156863 2653 | }, 2654 | "code": 11 2655 | } 2656 | }, 2657 | "blue": { 2658 | "name": "Blue", 2659 | "order": 4, 2660 | "normal": { 2661 | "name": "Blue", 2662 | "hex": "#89b4fa", 2663 | "rgb": { 2664 | "r": 137, 2665 | "g": 180, 2666 | "b": 250 2667 | }, 2668 | "hsl": { 2669 | "h": 217.1681415929203, 2670 | "s": 0.9186991869918699, 2671 | "l": 0.7588235294117647 2672 | }, 2673 | "code": 4 2674 | }, 2675 | "bright": { 2676 | "name": "Bright Blue", 2677 | "hex": "#74a8fc", 2678 | "rgb": { 2679 | "r": 116, 2680 | "g": 168, 2681 | "b": 252 2682 | }, 2683 | "hsl": { 2684 | "h": 217.05882352941174, 2685 | "s": 0.9577464788732396, 2686 | "l": 0.7215686274509804 2687 | }, 2688 | "code": 12 2689 | } 2690 | }, 2691 | "magenta": { 2692 | "name": "Magenta", 2693 | "order": 5, 2694 | "normal": { 2695 | "name": "Magenta", 2696 | "hex": "#f5c2e7", 2697 | "rgb": { 2698 | "r": 245, 2699 | "g": 194, 2700 | "b": 231 2701 | }, 2702 | "hsl": { 2703 | "h": 316.4705882352941, 2704 | "s": 0.7183098591549301, 2705 | "l": 0.8607843137254902 2706 | }, 2707 | "code": 5 2708 | }, 2709 | "bright": { 2710 | "name": "Bright Magenta", 2711 | "hex": "#f2aede", 2712 | "rgb": { 2713 | "r": 242, 2714 | "g": 174, 2715 | "b": 222 2716 | }, 2717 | "hsl": { 2718 | "h": 317.6470588235294, 2719 | "s": 0.7234042553191488, 2720 | "l": 0.8156862745098039 2721 | }, 2722 | "code": 13 2723 | } 2724 | }, 2725 | "cyan": { 2726 | "name": "Cyan", 2727 | "order": 6, 2728 | "normal": { 2729 | "name": "Cyan", 2730 | "hex": "#94e2d5", 2731 | "rgb": { 2732 | "r": 148, 2733 | "g": 226, 2734 | "b": 213 2735 | }, 2736 | "hsl": { 2737 | "h": 170.00000000000003, 2738 | "s": 0.5735294117647057, 2739 | "l": 0.7333333333333334 2740 | }, 2741 | "code": 6 2742 | }, 2743 | "bright": { 2744 | "name": "Bright Cyan", 2745 | "hex": "#6bd7ca", 2746 | "rgb": { 2747 | "r": 107, 2748 | "g": 215, 2749 | "b": 202 2750 | }, 2751 | "hsl": { 2752 | "h": 172.77777777777777, 2753 | "s": 0.5744680851063831, 2754 | "l": 0.6313725490196078 2755 | }, 2756 | "code": 14 2757 | } 2758 | }, 2759 | "white": { 2760 | "name": "White", 2761 | "order": 7, 2762 | "normal": { 2763 | "name": "White", 2764 | "hex": "#a6adc8", 2765 | "rgb": { 2766 | "r": 166, 2767 | "g": 173, 2768 | "b": 200 2769 | }, 2770 | "hsl": { 2771 | "h": 227.6470588235294, 2772 | "s": 0.23611111111111102, 2773 | "l": 0.7176470588235294 2774 | }, 2775 | "code": 7 2776 | }, 2777 | "bright": { 2778 | "name": "Bright White", 2779 | "hex": "#bac2de", 2780 | "rgb": { 2781 | "r": 186, 2782 | "g": 194, 2783 | "b": 222 2784 | }, 2785 | "hsl": { 2786 | "h": 226.66666666666669, 2787 | "s": 0.35294117647058837, 2788 | "l": 0.8 2789 | }, 2790 | "code": 15 2791 | } 2792 | } 2793 | } 2794 | } 2795 | } --------------------------------------------------------------------------------