diff --git a/.agents/skills/theme-definition/SKILL.md b/.agents/skills/theme-definition/SKILL.md new file mode 100644 index 00000000..dd4a478f --- /dev/null +++ b/.agents/skills/theme-definition/SKILL.md @@ -0,0 +1,109 @@ +--- +name: theme-definition +description: Create or update a bundled YAML theme source in the repository `themes/` directory when asked for a specific color theme such as Gruvbox, Nord, or a custom dark or light palette. These YAML files are compiled into TextMate `.tmTheme` files during the build. +--- + +# Theme Definition + +Use this skill when asked to create or update a bundled theme definition for a named color theme or palette. + +## Goal + +Create or update exactly one bundled theme source file in the repository top-level `themes/` directory: + +- `themes/.yml` + +Examples: + +- `Gruvbox Dark` -> `themes/gruvbox_dark.yml` +- `Nord Light` -> `themes/nord_light.yml` +- `My Theme` -> `themes/my_theme.yml` + +If a matching file already exists, update it instead of creating a duplicate. + +The YAML source is the authored artifact. Amp's build compiles it into a generated `.tmTheme` file with the same key during `build.rs`. + +## Required Constraints + +- Only author bundled YAML theme sources in `themes/`. +- Do not manually create or edit generated `.tmTheme` files for bundled themes. +- Do not write the theme anywhere except the top-level `themes/` directory unless the user explicitly asks for something else. +- Use the semantic token-family standard in [references/token-color-standard.md](references/token-color-standard.md) whenever the user does not provide a custom scope map. +- Treat `palette` as the single source of truth for authored colors: + - define hex literals in `palette` + - reference palette keys from `settings` and `rules` + - do not place inline hex literals directly in `settings` or `rules` +- Match the actual compiler schema in `build/theme_compiler/`: + - required top-level keys: `name`, `settings`, `rules` + - optional top-level key: `palette` + - `palette` values must be hex colors + - required `settings` keys: `foreground`, `background`, `line_highlight` + - `settings.foreground`, `settings.background`, and `settings.line_highlight` must reference palette keys + - `rules` must not be empty + - each rule may contain `name`, `scope`, `foreground`, `background`, `font_style` + - `rules[*].foreground` and `rules[*].background`, when present, must reference palette keys + - each rule must define at least one of `foreground`, `background`, or `font_style` + - `scope` must be a single valid TextMate selector string + - `font_style` values are `bold`, `italic`, and `underline` +- Treat unknown YAML keys as invalid rather than inventing extra structure. + +Amp requires these base theme settings: + +- `settings.foreground` +- `settings.background` +- `settings.line_highlight` + +When the user does not provide a complete scope list, do not stop at a small "practical first pass". Map the requested palette onto the canonical token families in the reference file so common code tokens do not collapse to the default foreground. + +## Workflow + +1. Identify the requested theme name and whether it is dark, light, or otherwise palette-driven. +2. Inspect nearby files in `themes/` for filename and YAML rule-shape conventions. +3. Read [references/token-color-standard.md](references/token-color-standard.md) and choose colors for each required family. +4. Create or update a YAML theme source with: + - top-level `name` + - a `palette` containing the authored hex colors + - `settings.foreground`, `settings.background`, and `settings.line_highlight` as palette-key references + - `rules` covering the canonical token families in the reference, using the requested palette +5. Prefer broadly useful TextMate scopes and stable fallback tiers instead of copying an existing bundled theme's exact rule list. +6. Validate through the repository build path before finishing. + +## Output Guidelines + +### For Generated Or Updated Themes + +- Use a filename stem that matches the theme key Amp will expose in theme selection. +- Keep the YAML concise and readable rather than encoding generated `.tmTheme` structure by hand. +- Put literal hex values in `palette`, not directly in `settings` or per-rule color fields. +- If the requested palette is underspecified, make the smallest reasonable set of assumptions and state them briefly. +- Prefer semantically complete coverage over an artificially tiny rule set. +- Ensure the base settings are sufficient for Amp's UI color mapping: + - `settings.foreground` is used for default text + - `settings.background` is used for inverted background mappings + - `settings.line_highlight` is used for the focused or current-line background +- Use the default foreground as a last-resort fallback, not as the intended color for common code tokens. +- Keep at least two punctuation tiers when the palette allows it: + - structural punctuation can stay muted + - semantic operators should remain clearly visible +- Distinguish the following families whenever the palette allows it: + - comments + - strings + - numbers and constants + - keywords and storage + - functions and methods + - types and namespaces + - local variables + - parameters + - support or builtin symbols + - annotations or attributes + - semantic operators + - structural punctuation +- Rust is a useful stress case for validation, but the output must remain cross-language and useful for markup and configuration formats too. + +### For Validation + +- Prefer `cargo check` as the main smoke test. It runs `build.rs`, compiles `themes/*.yml`, and loads the generated bundled themes. +- Use `cargo test --test theme_compiler` when validating compiler-schema behavior or debugging theme-source failures. +- Treat inline color literals outside `palette` as source-format errors. +- If there is no dedicated theme test for a specific change, still perform at least a build-path smoke check before finishing. +- When updating a bundled example theme, prefer adding or running a test that confirms the compiled theme loads and that key token families are represented by explicit scope rules. diff --git a/.agents/skills/theme-definition/references/token-color-standard.md b/.agents/skills/theme-definition/references/token-color-standard.md new file mode 100644 index 00000000..14e7031d --- /dev/null +++ b/.agents/skills/theme-definition/references/token-color-standard.md @@ -0,0 +1,95 @@ +# Token Color Standard + +Use this reference when generating or updating a bundled YAML theme source in `themes/` and the user has not provided a detailed scope map. The authored file is YAML, but the rule scopes should still target stable TextMate token families because Amp compiles the source into a `.tmTheme` during the build. + +For authored theme sources in this repo, `palette` is the only place for literal hex colors. `settings` and `rules` must reference palette keys so color intent stays named and reviewable. + +## Goal + +Map a palette onto stable semantic token families so common syntax elements stay differentiated across languages. Rust is the stress case: if a verbose Rust file still looks mostly like plain foreground text, coverage is too weak. + +## Core Rules + +- Start with broad TextMate scope families, not language-specific one-offs. +- Use the base foreground only for truly unclassified text and low-signal fallback. +- Prefer distinct hues for major semantic families over minimalist sameness. +- Keep structural punctuation readable but quieter than semantic operators. +- Parameters must not share the plain-text color when local variables are also colored. +- Support or builtin scopes should usually differ from user-defined names. + +## Canonical Families + +Every generated theme should include explicit selectors for these families unless the palette is intentionally constrained. + +| Family | Purpose | Typical selectors | +| --- | --- | --- | +| Plain text | Unclassified fallback text | `variable`, `source`, `text` fallback only | +| Comments | Comments and docs | `comment`, `comment.block.documentation`, `punctuation.definition.comment` | +| Strings | String bodies | `string`, `string.quoted`, `string.unquoted` | +| String escapes | Escape sequences and regex escapes | `constant.character.escape`, `constant.other.escape`, `string.regexp` | +| Numbers | Numeric literals | `constant.numeric` | +| Constants | Language and user constants | `constant.language`, `constant.character`, `constant.other`, `support.constant` | +| Keywords | Control flow and declarations | `keyword`, `keyword.control`, `keyword.declaration`, `keyword.other` | +| Storage/modifiers | Types, modifiers, mutability, ownership-like markers | `storage`, `storage.type`, `storage.modifier` | +| Functions and methods | Declared and invoked callables | `entity.name.function`, `meta.function-call`, `support.function`, `variable.function` | +| Types | Structs, enums, classes, traits, primitive types | `entity.name.type`, `entity.name.class`, `entity.name.struct`, `entity.name.enum`, `entity.name.trait`, `support.type` | +| Namespaces/modules | Paths, modules, packages | `entity.name.namespace`, `entity.name.module`, `support.module` | +| Macros/preprocessor | Macro-like or generated forms | `entity.name.macro`, `support.macro`, `meta.preprocessor` | +| Local variables | Normal bindings and fields when exposed as variables | `variable.other`, `variable.object`, `variable.other.member` | +| Parameters | Function and closure parameters | `variable.parameter` | +| Language/self variables | `self`, `this`, shell vars, special bindings | `variable.language`, `support.variable` | +| Attributes/annotations | Rust attributes, decorators, annotation names | `entity.other.attribute-name`, `storage.annotation`, `punctuation.definition.annotation` | +| Semantic operators | Accessors, assignment, ranges, arrows, logical ops | `keyword.operator`, `keyword.operator.assignment`, `keyword.operator.accessor`, `keyword.operator.range` | +| Structural punctuation | Braces, commas, delimiters, separators | `punctuation.separator`, `punctuation.terminator`, `meta.brace`, `meta.delimiter`, `punctuation.section` | +| Markup/config extras | Tags, headings, emphasis, diffs | `entity.name.tag`, `markup.heading`, `markup.bold`, `markup.italic`, `markup.inserted`, `markup.deleted` | +| Invalid/deprecated | Errors and deprecated syntax | `invalid`, `invalid.deprecated` | + +## Fallback Order + +Use this fallback order when a palette is underspecified: + +1. Comments +2. Strings +3. Numbers/constants +4. Keywords/storage +5. Functions +6. Types/namespaces +7. Variables/parameters +8. Support or builtin symbols +9. Attributes/annotations +10. Operators +11. Structural punctuation +12. Plain text fallback + +Do not skip from a specialized family straight to plain text if a nearby family already expresses similar semantics. For example: + +- `variable.parameter` should fall back to the variable family, not the base foreground. +- `support.function` should fall back to function or support coloring, not plain text. +- `entity.name.namespace` should fall back to types or support, not plain text. + +## Palette Mapping Guidance + +- Comments: muted and lower-contrast than code. +- Strings: warm or otherwise clearly distinct from comments and keywords. +- Numbers/constants: usually share a family, but language constants may be slightly stronger. +- Keywords/storage: strong and consistent; these anchor the syntax. +- Functions: distinct from types and variables. +- Types/namespaces: related but not identical when the palette has enough room. +- Local variables: subtle but still distinguishable from plain text. +- Parameters: warmer or otherwise more specific than local variables. +- Support/builtins: separate from user-defined names when possible. +- Attributes/annotations: visible but not louder than keywords. +- Semantic operators: visible enough to show expression structure. +- Structural punctuation: muted but never invisible. + +## Validation Checklist + +Before finishing, confirm: + +- The theme parses through Syntect. +- The theme contains explicit selectors for parameters, support or builtins, annotations or attributes, operators, and structural punctuation. +- A Rust-heavy file such as `build.rs` would show visible differences between: + - function names and type names + - parameters and local variables + - namespace paths and plain text + - semantic operators and structural delimiters diff --git a/AGENTS.md b/AGENTS.md index c03bf7ff..e4d0fd75 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ ## Project Structure & Module Organization - `src/` contains the Rust source: `main.rs` bootstraps the app, `lib.rs` exposes core logic. - Key modules live under `src/commands/`, `src/models/`, `src/view/`, `src/input/`, `src/presenters/`, and `src/util/`. -- Themes and defaults are stored under `src/themes/` and `src/models/application/preferences/`. +- Bundled theme sources and defaults are stored under `themes/` and `src/models/application/preferences/`. - Documentation sources live in `documentation/` (Zensical/MkDocs content). - Benchmarks live in `benches/`. - For a deeper walkthrough of module roles, the event loop, and command/keymap mechanics, see `docs/architecture.md`. diff --git a/Cargo.lock b/Cargo.lock index 82eb6837..173cecd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,8 @@ dependencies = [ "mio 1.0.3", "regex", "scribe", + "serde", + "serde_yaml", "serial_test", "signal-hook 0.1.17", "signal-hook-mio", @@ -1611,6 +1613,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "serial_test" version = "3.2.0" @@ -1881,6 +1896,12 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "url" version = "2.5.7" diff --git a/Cargo.toml b/Cargo.toml index 788a200e..c5fbf6d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,9 +11,12 @@ readme = "README.md" license-file = "LICENSE" keywords = ["text", "editor", "terminal", "modal"] edition="2021" +build = "build/main.rs" [build-dependencies] regex = "1.10" +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.9" syntect = "5.1" [dependencies] @@ -50,6 +53,8 @@ default-features = false # removes unused openssl dependency [dev-dependencies] criterion = "0.5" +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.9" [[bench]] name = "draw_buffer" diff --git a/build.rs b/build/main.rs similarity index 84% rename from build.rs rename to build/main.rs index 33e8a4a8..0c7424f9 100644 --- a/build.rs +++ b/build/main.rs @@ -1,3 +1,5 @@ +mod theme_compiler; + use regex::Regex; use std::env; use std::fs::{self, read_to_string, File}; @@ -6,15 +8,19 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::result::Result; use syntect::dumps::dump_to_uncompressed_file; +use syntect::highlighting::ThemeSet; use syntect::parsing::SyntaxSet; const COMMAND_REGEX: &str = r"pub fn (.*)\(app: &mut Application\) -> Result"; const APP_SYNTAX_DIR: &str = "syntaxes"; const APP_SYNTAX_SOURCE: &str = "app_syntaxes.packdump"; +const APP_THEME_DIR: &str = "themes"; +const APP_THEME_SOURCE: &str = "app_themes.packdump"; fn main() { generate_commands(); bake_app_syntaxes(); + bake_app_themes(); set_build_revision(); } @@ -129,3 +135,15 @@ fn bake_app_syntaxes() { dump_to_uncompressed_file(&builder.build(), output_path) .expect("Failed to write bundled syntax dump"); } + +fn bake_app_themes() { + let out_dir = env::var("OUT_DIR").expect("The compiler did not provide $OUT_DIR"); + let output_path = PathBuf::from(out_dir).join(APP_THEME_SOURCE); + let compiled_theme_dir = PathBuf::from(env::var("OUT_DIR").unwrap()).join("compiled_themes"); + theme_compiler::compile_themes(Path::new(APP_THEME_DIR), &compiled_theme_dir) + .expect("Failed to compile bundled theme sources"); + let theme_set = ThemeSet::load_from_folder(&compiled_theme_dir) + .expect("Failed to load compiled bundled themes"); + + dump_to_uncompressed_file(&theme_set, output_path).expect("Failed to write bundled theme dump"); +} diff --git a/build/theme_compiler/mod.rs b/build/theme_compiler/mod.rs new file mode 100644 index 00000000..8be62436 --- /dev/null +++ b/build/theme_compiler/mod.rs @@ -0,0 +1,67 @@ +mod parsed; +mod textmate; +mod validated; + +use std::collections::HashSet; +use std::fs; +use std::path::{Path, PathBuf}; + +pub use validated::Theme; + +pub fn compile_themes(source_dir: &Path, output_dir: &Path) -> Result, String> { + if output_dir.exists() { + fs::remove_dir_all(output_dir) + .map_err(|error| format!("Failed to clear generated theme directory: {error}"))?; + } + + fs::create_dir_all(output_dir) + .map_err(|error| format!("Failed to create generated theme directory: {error}"))?; + + let mut themes = Vec::new(); + let mut seen_keys = HashSet::new(); + for entry in fs::read_dir(source_dir) + .map_err(|error| format!("Failed to read theme source directory: {error}"))? + { + let path = entry + .map_err(|error| format!("Failed to read theme source entry: {error}"))? + .path(); + if !path.is_file() || path.extension().and_then(|ext| ext.to_str()) != Some("yml") { + continue; // skip non-yaml files + } + + let key = path + .file_stem() + .and_then(|stem| stem.to_str()) + .ok_or_else(|| format!("Invalid theme source filename: {}", path.display()))? + .to_string(); + + if !seen_keys.insert(key.clone()) { + return Err(format!("Duplicate theme key: {key}")); + } + + let content = fs::read_to_string(&path) + .map_err(|error| format!("Failed to read {}: {error}", path.display()))?; + let theme = parse_theme(&content) + .map_err(|error| format!("Failed to compile {key}.yml: {error}"))?; + themes.push((key.clone(), theme)); + } + + let mut outputs = Vec::new(); + for (key, theme) in themes { + let output_path = output_dir.join(format!("{key}.tmTheme")); + fs::write(&output_path, render_tmtheme(&theme)) + .map_err(|error| format!("Failed to write {}: {error}", output_path.display()))?; + outputs.push(output_path); + } + + Ok(outputs) +} + +pub fn parse_theme(content: &str) -> Result { + let parsed_theme = parsed::parse(content)?; + validated::Theme::try_from_parsed(parsed_theme) +} + +pub fn render_tmtheme(theme: &Theme) -> String { + textmate::render(theme) +} diff --git a/build/theme_compiler/parsed.rs b/build/theme_compiler/parsed.rs new file mode 100644 index 00000000..56d50ab2 --- /dev/null +++ b/build/theme_compiler/parsed.rs @@ -0,0 +1,116 @@ +use std::collections::BTreeMap; +use std::str::FromStr; + +use serde::de::{self, Deserializer}; +use serde::Deserialize; +use syntect::highlighting::ScopeSelectors; + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Theme { + pub name: String, + #[serde(default)] + pub palette: BTreeMap, + pub settings: Settings, + pub rules: Vec, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Settings { + pub foreground: PaletteKey, + pub background: PaletteKey, + pub line_highlight: PaletteKey, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Rule { + pub name: Option, + pub scope: ScopeSelector, + pub foreground: Option, + pub background: Option, + pub font_style: Option>, +} + +#[derive(Debug, Clone)] +pub struct HexColor(pub String); + +#[derive(Debug, Clone)] +pub struct PaletteKey(pub String); + +#[derive(Debug, Clone)] +pub struct ScopeSelector(pub String); + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum FontStyle { + Bold, + Italic, + Underline, +} + +pub fn parse(content: &str) -> Result { + serde_yaml::from_str(content).map_err(|error| error.to_string()) +} + +impl<'de> Deserialize<'de> for HexColor { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + validate_literal_color(&value).map_err(de::Error::custom)?; + Ok(HexColor(value)) + } +} + +impl<'de> Deserialize<'de> for PaletteKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + if value.starts_with('#') { + validate_literal_color(&value).map_err(de::Error::custom)?; + Err(de::Error::custom( + "must reference a palette key; literal colors belong in palette", + )) + } else { + Ok(PaletteKey(value)) + } + } +} + +impl<'de> Deserialize<'de> for ScopeSelector { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + ScopeSelectors::from_str(&value).map_err(de::Error::custom)?; + Ok(ScopeSelector(value)) + } +} + +impl FontStyle { + pub fn as_str(&self) -> &'static str { + match self { + FontStyle::Bold => "bold", + FontStyle::Italic => "italic", + FontStyle::Underline => "underline", + } + } +} + +fn validate_literal_color(color: &str) -> Result<(), String> { + let is_valid = matches!(color.len(), 4 | 7 | 9) + && color.starts_with('#') + && color.chars().skip(1).all(|char| char.is_ascii_hexdigit()); + + if is_valid { + Ok(()) + } else { + Err("must be a hex color in #RGB, #RRGGBB, or #RRGGBBAA format".to_string()) + } +} diff --git a/build/theme_compiler/textmate.rs b/build/theme_compiler/textmate.rs new file mode 100644 index 00000000..b4df9a69 --- /dev/null +++ b/build/theme_compiler/textmate.rs @@ -0,0 +1,69 @@ +use std::fmt::Write as _; + +use super::validated; + +pub fn render(theme: &validated::Theme) -> String { + let mut output = String::new(); + output.push_str("\n"); + output.push_str("\n"); + output.push_str("\n"); + output.push_str("\n"); + write_key_string(&mut output, 1, "name", &theme.name); + output.push_str(" settings\n"); + output.push_str(" \n"); + output.push_str(" \n"); + output.push_str(" settings\n"); + output.push_str(" \n"); + write_key_string(&mut output, 4, "foreground", &theme.settings.foreground); + write_key_string(&mut output, 4, "background", &theme.settings.background); + write_key_string( + &mut output, + 4, + "lineHighlight", + &theme.settings.line_highlight, + ); + output.push_str(" \n"); + output.push_str(" \n"); + + for rule in &theme.rules { + output.push_str(" \n"); + if let Some(name) = &rule.name { + write_key_string(&mut output, 3, "name", name); + } + write_key_string(&mut output, 3, "scope", &rule.scope); + output.push_str(" settings\n"); + output.push_str(" \n"); + if let Some(foreground) = &rule.foreground { + write_key_string(&mut output, 4, "foreground", foreground); + } + if let Some(background) = &rule.background { + write_key_string(&mut output, 4, "background", background); + } + if let Some(font_style) = &rule.font_style { + write_key_string(&mut output, 4, "fontStyle", &font_style.join(" ")); + } + output.push_str(" \n"); + output.push_str(" \n"); + } + + output.push_str(" \n"); + output.push_str("\n"); + output.push_str("\n"); + output +} + +fn write_key_string(output: &mut String, indent: usize, key: &str, value: &str) { + let padding = " ".repeat(indent); + let escaped = xml_escape(value); + let _ = writeln!(output, "{padding}{key}"); + let _ = writeln!(output, "{padding}{escaped}"); +} + +fn xml_escape(value: &str) -> String { + value + .replace('&', "&") + .replace('<', "<") + .replace('>', ">") + .replace('"', """) + .replace('\'', "'") +} diff --git a/build/theme_compiler/validated.rs b/build/theme_compiler/validated.rs new file mode 100644 index 00000000..e8bd48fa --- /dev/null +++ b/build/theme_compiler/validated.rs @@ -0,0 +1,101 @@ +use std::collections::BTreeMap; + +use super::parsed; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Theme { + pub name: String, + pub settings: Settings, + pub rules: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Settings { + pub foreground: String, + pub background: String, + pub line_highlight: String, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Rule { + pub name: Option, + pub scope: String, + pub foreground: Option, + pub background: Option, + pub font_style: Option>, +} + +impl Theme { + pub fn try_from_parsed(parsed_theme: parsed::Theme) -> Result { + let palette = parsed_theme + .palette + .into_iter() + .map(|(key, value)| (key, value.0)) + .collect::>(); + + let settings = Settings { + foreground: resolve_palette_key("settings.foreground", parsed_theme.settings.foreground, &palette)?, + background: resolve_palette_key("settings.background", parsed_theme.settings.background, &palette)?, + line_highlight: resolve_palette_key( + "settings.line_highlight", + parsed_theme.settings.line_highlight, + &palette, + )?, + }; + + if parsed_theme.rules.is_empty() { + return Err("rules must not be empty".to_string()); + } + + let mut rules = Vec::with_capacity(parsed_theme.rules.len()); + for (index, parsed_rule) in parsed_theme.rules.into_iter().enumerate() { + let path = format!("rules[{index}]"); + let foreground = parsed_rule + .foreground + .map(|value| resolve_palette_key(&format!("{path}.foreground"), value, &palette)) + .transpose()?; + let background = parsed_rule + .background + .map(|value| resolve_palette_key(&format!("{path}.background"), value, &palette)) + .transpose()?; + let font_style = parsed_rule.font_style.map(|styles| { + styles + .into_iter() + .map(|style| style.as_str().to_string()) + .collect::>() + }); + + if foreground.is_none() && background.is_none() && font_style.is_none() { + return Err(format!( + "{path} must define at least one of foreground, background, or font_style" + )); + } + + rules.push(Rule { + name: parsed_rule.name, + scope: parsed_rule.scope.0, + foreground, + background, + font_style, + }); + } + + Ok(Self { + name: parsed_theme.name, + settings, + rules, + }) + } +} + +fn resolve_palette_key( + path: &str, + color_ref: parsed::PaletteKey, + palette: &BTreeMap, +) -> Result { + let key = color_ref.0; + palette + .get(&key) + .cloned() + .ok_or_else(|| format!("{path} references unknown palette key: {key}")) +} diff --git a/docs/architecture.md b/docs/architecture.md index 3693ba65..959abe33 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -16,7 +16,7 @@ Amp is a terminal text editor with a clear separation between state, command log - `src/view/`: terminal rendering, scroll regions, render caches, theming, and event listening. - `src/presenters/`: mode-specific renderers that format workspace state into view components. - `src/util/`: shared helpers (tokens, lexing, selection helpers). -- `src/themes/`: bundled TextMate theme files. +- `themes/`: bundled YAML theme sources compiled into TextMate themes at build time. ## Modes and Presentation Modes are defined in `src/models/application/modes/` and collected into the `Mode` enum. Each mode has a corresponding presenter under `src/presenters/modes/` that renders the UI for that mode using a `Presenter` built from the `View`. diff --git a/src/models/application/mod.rs b/src/models/application/mod.rs index fc851f1c..4f8c4a12 100644 --- a/src/models/application/mod.rs +++ b/src/models/application/mod.rs @@ -2,6 +2,7 @@ mod clipboard; mod event; pub mod modes; mod preferences; +mod syntax_loader; // Published API pub use self::clipboard::ClipboardContent; @@ -11,6 +12,7 @@ pub use self::preferences::Preferences; use self::clipboard::Clipboard; use self::modes::*; +use self::syntax_loader::SyntaxLoader; use crate::commands; use crate::errors::*; use crate::presenters; @@ -26,7 +28,6 @@ use std::mem; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::mpsc::{self, Receiver, Sender}; -use syntect::dumps::from_uncompressed_data; use syntect::parsing::SyntaxSet; pub struct Application { @@ -471,18 +472,7 @@ fn create_workspace( } fn build_full_syntax_set() -> Result { - // Load syntect default + app-bundled syntax sets serialized in build.rs - let mut builder = from_uncompressed_data::(include_bytes!(concat!( - env!("OUT_DIR"), - "/app_syntaxes.packdump" - ))) - .context("Couldn't load bundled syntax definitions")? - .into_builder(); - - // Add user syntaxes to built-in set - builder.add_from_folder(user_syntax_path()?, true)?; - - Ok(builder.build()) + SyntaxLoader::new(user_syntax_path()?).load() } #[cfg(not(test))] diff --git a/src/models/application/modes/symbol_jump.rs b/src/models/application/modes/symbol_jump.rs index a2c2605d..a1b2680a 100644 --- a/src/models/application/modes/symbol_jump.rs +++ b/src/models/application/modes/symbol_jump.rs @@ -214,12 +214,15 @@ mod tests { let config = SearchSelectConfig::default(); let mut mode = SymbolJumpMode::new(config.clone()).unwrap(); let mut app = Application::new(&[]).unwrap(); - app.workspace.open_buffer(&Path::new("build.rs")).unwrap(); + + // Open this file so the test can search for its own function symbol. + let path = Path::new(env!("CARGO_MANIFEST_DIR")).join(file!()); + app.workspace.open_buffer(&path).unwrap(); let token_set = app.workspace.current_buffer_tokens().unwrap(); // Do an initial reset to get the results populated mode.reset(&token_set, config.clone()).unwrap(); - mode.query().push_str("main"); + mode.query().push_str("reset_clears_query_mode_and_results"); mode.set_insert_mode(false); mode.search(); diff --git a/src/models/application/preferences/mod.rs b/src/models/application/preferences/mod.rs index 2cbdb408..432e4a99 100644 --- a/src/models/application/preferences/mod.rs +++ b/src/models/application/preferences/mod.rs @@ -2,7 +2,7 @@ use crate::errors::*; use crate::input::KeyMap; use crate::models::application::modes::open; use crate::models::application::modes::SearchSelectConfig; -use app_dirs2::{app_dir, app_root, get_app_root, AppDataType, AppInfo}; +use app_dirs2::{app_root, get_app_root, AppDataType, AppInfo}; use bloodhound::ExclusionPattern; use scribe::Buffer; use std::fs::OpenOptions; @@ -98,8 +98,14 @@ impl Preferences { /// A path pointing to the user syntax definition directory. pub fn syntax_path() -> Result { - app_dir(AppDataType::UserConfig, &APP_INFO, SYNTAX_PATH) - .context("Couldn't create syntax directory or build a path to it.") + config_subdirectory(SYNTAX_PATH) + .context("Couldn't build a path to the user syntax directory.") + } + + /// A path pointing to the user theme directory. + pub fn theme_path() -> Result { + config_subdirectory(THEME_PATH) + .context("Couldn't build a path to the user themes directory.") } /// Returns the preference file loaded into a buffer for editing. @@ -152,12 +158,6 @@ impl Preferences { .expect("Couldn't find default theme name!") } - /// Returns the theme path, making sure the directory exists. - pub fn theme_path(&self) -> Result { - app_dir(AppDataType::UserConfig, &APP_INFO, THEME_PATH) - .context("Couldn't create themes directory or build a path to it.") - } - /// Updates the in-memory theme value. pub fn set_theme>(&mut self, theme: T) { self.theme = Some(theme.into()); @@ -439,6 +439,14 @@ fn load_document() -> Result> { Ok(parsed_data.into_iter().next()) } +fn config_subdirectory(path: &str) -> Result { + let mut directory = app_root(AppDataType::UserConfig, &APP_INFO) + .context("Couldn't create preferences directory or build a path to it.")?; + directory.push(path); + + Ok(directory) +} + fn load_default_document() -> Result { YamlLoader::load_from_str(include_str!("default.yml")) .context("Couldn't parse default config file")? diff --git a/src/models/application/syntax_loader.rs b/src/models/application/syntax_loader.rs new file mode 100644 index 00000000..737fa948 --- /dev/null +++ b/src/models/application/syntax_loader.rs @@ -0,0 +1,57 @@ +use crate::errors::*; +use std::path::PathBuf; +use syntect::dumps::from_uncompressed_data; +use syntect::parsing::SyntaxSet; + +pub struct SyntaxLoader { + path: PathBuf, +} + +impl SyntaxLoader { + pub fn new(path: PathBuf) -> SyntaxLoader { + SyntaxLoader { path } + } + + pub fn load(self) -> Result { + // Load syntect default + app-bundled syntax sets serialized in build.rs. + let mut builder = from_uncompressed_data::(include_bytes!(concat!( + env!("OUT_DIR"), + "/app_syntaxes.packdump" + ))) + .context("Couldn't load bundled syntax definitions")? + .into_builder(); + + // Merge user-defined syntaxes when a user syntax directory is present. + if self.path.is_dir() { + builder.add_from_folder(&self.path, true)?; + } + + Ok(builder.build()) + } +} + +#[cfg(test)] +mod tests { + use super::SyntaxLoader; + use std::path::PathBuf; + + #[test] + fn load_includes_bundled_and_fixture_syntaxes() { + let syntax_set = SyntaxLoader::new(PathBuf::from("tests/fixtures/user_syntaxes")) + .load() + .unwrap(); + + assert!(syntax_set.find_syntax_by_name("Rust").is_some()); + assert!(syntax_set.find_syntax_by_name("Amp").is_some()); + } + + #[test] + fn load_ignores_missing_user_syntax_directory() { + let missing_path = PathBuf::from("tests/fixtures/missing_syntaxes"); + assert!(!missing_path.exists()); + + let syntax_set = SyntaxLoader::new(missing_path).load().unwrap(); + + assert!(syntax_set.find_syntax_by_name("Rust").is_some()); + } +} diff --git a/src/themes/solarized_dark.tmTheme b/src/themes/solarized_dark.tmTheme deleted file mode 100644 index 47bd6035..00000000 --- a/src/themes/solarized_dark.tmTheme +++ /dev/null @@ -1,2061 +0,0 @@ - - - - - name - Solarized Dark - settings - - - settings - - background - #002B36 - caret - #839496 - foreground - #b2b2b2 - invisibles - #073642 - lineHighlight - #303030 - selection - #EEE8D5 - - - - name - Comment - scope - comment - settings - - fontStyle - - foreground - #586E75 - - - - name - String - scope - string - settings - - foreground - #2AA198 - - - - name - StringNumber - scope - string - settings - - foreground - #586E75 - - - - name - Regexp - scope - string.regexp - settings - - foreground - #DC322F - - - - name - Number - scope - constant.numeric - settings - - foreground - #D33682 - - - - name - Variable - scope - variable.language, variable.other - settings - - foreground - #268BD2 - - - - name - Keyword - scope - keyword - settings - - foreground - #859900 - - - - name - Storage - scope - storage - settings - - fontStyle - - foreground - #859900 - - - - name - Class name - scope - entity.name.class, entity.name.type.class - settings - - foreground - #268BD2 - - - - name - Function name - scope - entity.name.function - settings - - foreground - #268BD2 - - - - name - Variable start - scope - punctuation.definition.variable - settings - - foreground - #859900 - - - - name - Embedded code markers - scope - punctuation.section.embedded.begin, punctuation.section.embedded.end - settings - - foreground - #DC322F - - - - name - Built-in constant - scope - constant.language, meta.preprocessor - settings - - foreground - #B58900 - - - - name - Support.construct - scope - support.function.construct, keyword.other.new - settings - - foreground - #DC322F - - - - name - User-defined constant - scope - constant.character, constant.other - settings - - foreground - #CB4B16 - - - - name - Inherited class - scope - entity.other.inherited-class - settings - - - - name - Function argument - scope - variable.parameter - settings - - - - name - Tag name - scope - entity.name.tag - settings - - foreground - #268BD2 - - - - name - Tag start/end - scope - punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end - settings - - foreground - #586E75 - - - - name - Tag attribute - scope - entity.other.attribute-name - settings - - foreground - #93A1A1 - - - - name - Library function - scope - support.function - settings - - foreground - #268BD2 - - - - name - Continuation - scope - punctuation.separator.continuation - settings - - foreground - #DC322F - - - - name - Library constant - scope - support.constant - settings - - - - name - Library class/type - scope - support.type, support.class - settings - - foreground - #859900 - - - - name - Library Exception - scope - support.type.exception - settings - - foreground - #CB4B16 - - - - name - Special - scope - keyword.other.special-method - settings - - foreground - #CB4B16 - - - - name - Library variable - scope - support.other.variable - settings - - - - name - Invalid - scope - invalid - settings - - - - name - Quoted String - scope - string.quoted.double, string.quoted.single - settings - - foreground - #2AA198 - - - - name - Quotes - scope - punctuation.definition.string.begin, punctuation.definition.string.end - settings - - foreground - #DC322F - - - - name - CSS: Property name (body) - scope - entity.name.tag.css, support.type.property-name.css, meta.property-name.css, support.type.property-name.scss - settings - - fontStyle - - foreground - #839496 - - - - name - CSS: @ rules (purple) - scope - punctuation.definition.keyword.scss, punctuation.definition.keyword.css, keyword.control.at-rule.charset.css, keyword.control.at-rule.charset.scss, keyword.control.each.css, keyword.control.each.scss, keyword.control.else.css, keyword.control.else.scss, keyword.control.at-rule.import.css, keyword.control.at-rule.import.scss, keyword.control.at-rule.fontface.css, keyword.control.at-rule.fontface.scss, keyword.control.for.css, keyword.control.for.scss, keyword.control.at-rule.function.css, keyword.control.at-rule.function.scss, keyword.control.if.css, keyword.control.if.scss, keyword.control.at-rule.include.scss, keyword.control.at-rule.media.css, keyword.control.at-rule.media.scss, keyword.control.at-rule.font-face.css, keyword.control.at-rule.font-face.scss, meta.at-rule.import.css, variable.other.less, variable.declaration.less, variable.interpolation.less, meta.at-rule.media.scss - settings - - foreground - #6C71c4 - - - - name - CSS: Numeric Value (blue) - scope - constant.numeric.css, keyword.other.unit.css, keyword.unit.css, constant.other.color.rgb-value.css, constant.numeric.scss, constant.other.color.rgb-value.scss, keyword.other.unit.scss, punctuation.definition.constant.scss, punctuation.definition.constant.css, constant.other.rgb-value.css - settings - - fontStyle - - foreground - #268BD2 - - - - name - CSS: String, value and constants (azure) - scope - variable.parameter.url.scss, meta.property-value.css, meta.property-value.scss, support.constant.property-value.scss, support.constant.font-name.scss, string.quoted.single.css, string.quoted.double.css, constant.character.escaped.css, string.quoted.variable.parameter.url, punctuation.definition.string.begin.scss, punctuation.definition.string.begin.css, punctuation.definition.string.end.scss, punctuation.definition.string.end.css, support.constant.property-value.css - settings - - fontStyle - - foreground - #2AA198 - - - - name - CSS: !Important (red) - scope - keyword.other.important.css, keyword.other.important.scss - settings - - foreground - #DC322F - - - - name - CSS: Standard color value (orange) - scope - support.constant.color, invalid.deprecated.color.w3c-non-standard-color-name.scss - settings - - foreground - #CB4b16 - - - - name - CSS: : , () (body) - scope - punctuation.terminator.rule.css, punctuation.section.function.css, punctuation.section.function.scss, punctuation.separator.key-value.csspunctuation.scss, punctuation.css, keyword.operator.less, entity.name.tag.wildcard.scss, entity.name.tag.wildcard.css, entity.name.tag.reference.scss - settings - - fontStyle - - foreground - #657B83 - - - - name - CSS: Selector > [] and non-spec tags (body) - scope - meta.selector.css - settings - - fontStyle - - foreground - #657B83 - - - - name - CSS: Tag (green) - scope - entity.name.tag.css, entity.name.tag.scss - settings - - fontStyle - - foreground - #859900 - - - - name - CSS .class (yellow) - scope - entity.other.attribute-name.class.css, entity.other.less.mixin - settings - - fontStyle - - foreground - #B58900 - - - - name - CSS: #id (yellow) - scope - source.css entity.other.attribute-name.id, source.scss entity.other.attribute-name.id - settings - - foreground - #B58900 - - - - name - CSS :pseudo (orange) - scope - entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css - settings - - fontStyle - - foreground - #CB4B16 - - - - name - SCSS: Variables (pink) - scope - variable, variable.scss - settings - - foreground - #D33682 - - - - name - JS: Function Name - scope - meta.function.js, entity.name.function.js, support.function.dom.js - settings - - foreground - #B58900 - - - - name - JS: Source - scope - text.html.basic source.js.embedded.html - settings - - fontStyle - - foreground - #B58900 - - - - name - JS: Function - scope - storage.type.function.js - settings - - foreground - #268BD2 - - - - name - JS: Numeric Constant - scope - constant.numeric.js - settings - - foreground - #2AA198 - - - - name - JS: [] - scope - meta.brace.square.js - settings - - foreground - #268BD2 - - - - name - JS: Storage Type - scope - storage.type.js - settings - - foreground - #268BD2 - - - - name - () - scope - meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js - settings - - foreground - #93A1A1 - - - - name - {} - scope - meta.brace.curly.js - settings - - foreground - #839496 - - - - name - HTML: Doctype - scope - entity.name.tag.doctype.html, meta.tag.sgml.html, string.quoted.double.doctype.identifiers-and-DTDs.html - settings - - fontStyle - italic - foreground - #839496 - - - - name - HTML: Comment Block - scope - comment.block.html - settings - - fontStyle - italic - foreground - #839496 - - - - name - HTML: Script - scope - entity.name.tag.script.html - settings - - fontStyle - italic - - - - name - HTML: Style - scope - source.css.embedded.html string.quoted.double.html - settings - - fontStyle - - foreground - #2AA198 - - - - name - HTML: Text - scope - text.html.ruby - settings - - foreground - #839496 - - - - name - HTML: = - scope - text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html - settings - - fontStyle - - foreground - #657B83 - - - - name - HTML: something= - scope - text.html.basic entity.other.attribute-name.html - settings - - foreground - #657B83 - - - - name - HTML: " - scope - text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html, punctuation.definition.string.begin.html, punctuation.definition.string.end.html - settings - - fontStyle - - foreground - #2AA198 - - - - name - HTML: <tag> - scope - entity.name.tag.block.any.html - settings - - foreground - #268BD2 - - - - name - HTML: style - scope - source.css.embedded.html entity.name.tag.style.html - settings - - fontStyle - italic - - - - name - HTML: <style> - scope - entity.name.tag.style.html - settings - - fontStyle - - - - - name - HTML: {} - scope - text.html.basic, punctuation.section.property-list.css - settings - - fontStyle - - - - - name - HTML: Embeddable - scope - source.css.embedded.html, comment.block.html - settings - - fontStyle - italic - foreground - #839496 - - - - name - Ruby: Variable definition - scope - punctuation.definition.variable.ruby - settings - - fontStyle - - foreground - #268BD2 - - - - name - Ruby: Function Name - scope - meta.function.method.with-arguments.ruby - settings - - foreground - #657B83 - - - - name - Ruby: Variable - scope - variable.language.ruby - settings - - foreground - #2AA198 - - - - name - Ruby: Function - scope - entity.name.function.ruby - settings - - foreground - #268BD2 - - - - name - Ruby: Keyword Control - scope - keyword.control.ruby, keyword.control.def.ruby - settings - - foreground - #859900 - - - - name - Ruby: Class - scope - keyword.control.class.ruby, meta.class.ruby - settings - - foreground - #859900 - - - - name - Ruby: Class Name - scope - entity.name.type.class.ruby - settings - - fontStyle - - foreground - #B58900 - - - - name - Ruby: Keyword - scope - keyword.control.ruby - settings - - fontStyle - - foreground - #859900 - - - - name - Ruby: Support Class - scope - support.class.ruby - settings - - fontStyle - - foreground - #B58900 - - - - name - Ruby: Special Method - scope - keyword.other.special-method.ruby - settings - - foreground - #859900 - - - - name - Ruby: Constant - scope - constant.language.ruby, constant.numeric.ruby - settings - - foreground - #2AA198 - - - - name - Ruby: Constant Other - scope - variable.other.constant.ruby - settings - - fontStyle - - foreground - #B58900 - - - - name - Ruby: :symbol - scope - constant.other.symbol.ruby - settings - - fontStyle - - foreground - #2AA198 - - - - name - Ruby: Punctuation Section '' - scope - punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby - settings - - foreground - #DC322F - - - - name - Ruby: Special Method - scope - keyword.other.special-method.ruby - settings - - foreground - #CB4B16 - - - - name - PHP: Include - scope - keyword.control.import.include.php - settings - - foreground - #CB4B16 - - - - name - Ruby: erb = - scope - text.html.ruby meta.tag.inline.any.html - settings - - fontStyle - - foreground - #839496 - - - - name - Ruby: erb "" - scope - text.html.ruby punctuation.definition.string.begin, text.html.ruby punctuation.definition.string.end - settings - - fontStyle - - foreground - #2AA198 - - - - name - PHP: Quoted Single - scope - punctuation.definition.string.begin, punctuation.definition.string.end - settings - - foreground - #839496 - - - - name - PHP: Class Names - scope - support.class.php - settings - - foreground - #93A1A1 - - - - name - PHP: [] - scope - keyword.operator.index-start.php, keyword.operator.index-end.php - settings - - foreground - #DC322F - - - - name - PHP: Array - scope - meta.array.php - settings - - foreground - #586E75 - - - - name - PHP: Array() - scope - meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php - settings - - fontStyle - - foreground - #B58900 - - - - name - PHP: Array Construct - scope - support.function.construct.php - settings - - foreground - #B58900 - - - - name - PHP: Array Begin - scope - punctuation.definition.array.begin, punctuation.definition.array.end - settings - - foreground - #DC322F - - - - name - PHP: Numeric Constant - scope - constant.numeric.php - settings - - foreground - #2AA198 - - - - name - PHP: New - scope - keyword.other.new.php - settings - - foreground - #CB4B16 - - - - name - PHP: :: - scope - keyword.operator.class - settings - - fontStyle - - foreground - #93A1A1 - - - - name - PHP: Other Property - scope - variable.other.property.php - settings - - foreground - #839496 - - - - name - PHP: Class - scope - storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php - settings - - foreground - #B58900 - - - - name - PHP: Semicolon - scope - punctuation.terminator.expression.php - settings - - foreground - #839496 - - - - name - PHP: Inherited Class - scope - meta.other.inherited-class.php - settings - - fontStyle - - foreground - #586E75 - - - - name - PHP: Storage Type - scope - storage.type.php - settings - - foreground - #859900 - - - - name - PHP: Function - scope - entity.name.function.php - settings - - foreground - #839496 - - - - name - PHP: Function Construct - scope - support.function.construct.php - settings - - foreground - #859900 - - - - name - PHP: Function Call - scope - entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php - settings - - foreground - #839496 - - - - name - PHP: Comment - scope - keyword.other.phpdoc - settings - - fontStyle - - foreground - #839496 - - - - name - PHP: Source Emebedded - scope - source.php.embedded.block.html - settings - - foreground - #CB4B16 - - - - name - PHP: Storage Type Function - scope - storage.type.function.php - settings - - foreground - #CB4B16 - - - - name - C: constant - scope - constant.numeric.c - settings - - fontStyle - - foreground - #2AA198 - - - - name - C: Meta Preprocessor - scope - meta.preprocessor.c.include, meta.preprocessor.macro.c - settings - - fontStyle - - foreground - #CB4B16 - - - - name - C: Keyword - scope - keyword.control.import.define.c, keyword.control.import.include.c - settings - - fontStyle - - foreground - #CB4B16 - - - - name - C: Function Preprocessor - scope - entity.name.function.preprocessor.c - settings - - fontStyle - - foreground - #CB4B16 - - - - name - C: include <something.c> - scope - meta.preprocessor.c.include string.quoted.other.lt-gt.include.c, meta.preprocessor.c.include punctuation.definition.string.begin.c, meta.preprocessor.c.include punctuation.definition.string.end.c - settings - - fontStyle - - foreground - #2AA198 - - - - name - C: Function - scope - support.function.C99.c, support.function.any-method.c, entity.name.function.c - settings - - fontStyle - - foreground - #93A1A1 - - - - name - C: " - scope - punctuation.definition.string.begin.c, punctuation.definition.string.end.c - settings - - fontStyle - - foreground - #2AA198 - - - - name - C: Storage Type - scope - storage.type.c - settings - - fontStyle - - foreground - #B58900 - - - - name - diff: header - scope - meta.diff, meta.diff.header - settings - - background - #B58900 - fontStyle - italic - foreground - #EEE8D5 - - - - name - diff: deleted - scope - markup.deleted - settings - - background - #EEE8D5 - fontStyle - - foreground - #DC322F - - - - name - diff: changed - scope - markup.changed - settings - - background - #EEE8D5 - fontStyle - - foreground - #CB4B16 - - - - name - diff: inserted - scope - markup.inserted - settings - - background - #EEE8D5 - foreground - #2AA198 - - - - name - reST raw - scope - text.restructuredtext markup.raw - settings - - foreground - #2AA198 - - - - name - Other: Removal - scope - other.package.exclude, other.remove - settings - - fontStyle - - foreground - #DC322F - - - - name - Other: Add - scope - other.add - settings - - foreground - #2AA198 - - - - name - Tex: {} - scope - punctuation.section.group.tex , punctuation.definition.arguments.begin.latex, punctuation.definition.arguments.end.latex, punctuation.definition.arguments.latex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: {text} - scope - meta.group.braces.tex - settings - - fontStyle - - foreground - #B58900 - - - - name - Tex: Other Math - scope - string.other.math.tex - settings - - fontStyle - - foreground - #B58900 - - - - name - Tex: {var} - scope - variable.parameter.function.latex - settings - - fontStyle - - foreground - #CB4B16 - - - - name - Tex: Math \\ - scope - punctuation.definition.constant.math.tex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: Constant Math - scope - text.tex.latex constant.other.math.tex, constant.other.general.math.tex, constant.other.general.math.tex, constant.character.math.tex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Tex: Other Math String - scope - string.other.math.tex - settings - - fontStyle - - foreground - #B58900 - - - - name - Tex: $ - scope - punctuation.definition.string.begin.tex, punctuation.definition.string.end.tex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: \label - scope - keyword.control.label.latex, text.tex.latex constant.other.general.math.tex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Tex: \label { } - scope - variable.parameter.definition.label.latex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: Function - scope - support.function.be.latex - settings - - fontStyle - - foreground - #859900 - - - - name - Tex: Support Function Section - scope - support.function.section.latex - settings - - fontStyle - - foreground - #CB4B16 - - - - name - Tex: Support Function - scope - support.function.general.tex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Tex: Comment - scope - punctuation.definition.comment.tex, comment.line.percentage.tex - settings - - fontStyle - italic - - - - name - Tex: Reference Label - scope - keyword.control.ref.latex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Python: storage - scope - storage.type.class.python, storage.type.function.python, storage.modifier.global.python - settings - - fontStyle - - foreground - #859900 - - - - name - Python: import - scope - keyword.control.import.python, keyword.control.import.from.python - settings - - foreground - #CB4B16 - - - - name - Python: Support.exception - scope - support.type.exception.python - settings - - foreground - #B58900 - - - - name - Shell: builtin - scope - support.function.builtin.shell - settings - - foreground - #859900 - - - - name - Shell: variable - scope - variable.other.normal.shell - settings - - foreground - #CB4B16 - - - - name - Shell: DOT_FILES - scope - source.shell - settings - - fontStyle - - foreground - #268BD2 - - - - name - Shell: meta scope in loop - scope - meta.scope.for-in-loop.shell, variable.other.loop.shell - settings - - fontStyle - - foreground - #586E75 - - - - name - Shell: "" - scope - punctuation.definition.string.end.shell, punctuation.definition.string.begin.shell - settings - - fontStyle - - foreground - #859900 - - - - name - Shell: Meta Block - scope - meta.scope.case-block.shell, meta.scope.case-body.shell - settings - - fontStyle - - foreground - #586E75 - - - - name - Shell: [] - scope - punctuation.definition.logical-expression.shell - settings - - fontStyle - - foreground - #DC322F - - - - name - Shell: Comment - scope - comment.line.number-sign.shell - settings - - fontStyle - italic - - - - name - Java: import - scope - keyword.other.import.java - settings - - fontStyle - - foreground - #CB4B16 - - - - name - Java: meta-import - scope - storage.modifier.import.java - settings - - fontStyle - - foreground - #586E75 - - - - name - Java: Class - scope - meta.class.java storage.modifier.java - settings - - fontStyle - - foreground - #B58900 - - - - name - Java: /* comment */ - scope - source.java comment.block - settings - - fontStyle - - foreground - #586E75 - - - - name - Java: /* @param */ - scope - comment.block meta.documentation.tag.param.javadoc keyword.other.documentation.param.javadoc - settings - - fontStyle - - foreground - #586E75 - - - - name - Perl: variables - scope - punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl - settings - - foreground - #B58900 - - - - name - Perl: functions - scope - support.function.perl - settings - - foreground - #859900 - - - - name - Perl: comments - scope - comment.line.number-sign.perl - settings - - fontStyle - italic - foreground - #586E75 - - - - name - Perl: quotes - scope - punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl - settings - - foreground - #2AA198 - - - - name - Perl: \char - scope - constant.character.escape.perl - settings - - foreground - #DC322F - - - - Name - Markdown punctuation - scope - markup.list, text.html.markdown punctuation.definition, meta.separator.markdown - settings - - foreground - #CB4b16 - - - - Name - Markdown heading - scope - markup.heading - settings - - foreground - #268BD2 - - - - Name - Markdown text inside some block element - scope - markup.quote, meta.paragraph.list - settings - - foreground - #2AA198 - - - - Name - Markdown em - scope - markup.italic - settings - - fontStyle - italic - - - - Name - Markdown strong - scope - markup.bold - settings - - fontStyle - bold - - - - Name - Markdown reference - scope - markup.underline.link.markdown, meta.link.inline punctuation.definition.metadata, meta.link.reference.markdown punctuation.definition.constant, meta.link.reference.markdown constant.other.reference - settings - - foreground - #B58900 - - - - Name - Markdown linebreak - scope - meta.paragraph.markdown meta.dummy.line-break - settings - - background - #6C71c4 - - - - - name - GitGutter deleted - scope - markup.deleted.git_gutter - settings - - foreground - #F92672 - - - - name - GitGutter inserted - scope - markup.inserted.git_gutter - settings - - foreground - #A6E22E - - - - name - GitGutter changed - scope - markup.changed.git_gutter - settings - - foreground - #967EFB - - - - - name - SublimeLinter Annotations - scope - sublimelinter.notes - settings - - background - #eee8d5 - foreground - #eee8d5 - - - - name - SublimeLinter Error Outline - scope - sublimelinter.outline.illegal - settings - - background - #93a1a1 - foreground - #93a1a1 - - - - name - SublimeLinter Error Underline - scope - sublimelinter.underline.illegal - settings - - background - #dc322f - - - - name - SublimeLinter Warning Outline - scope - sublimelinter.outline.warning - settings - - background - #839496 - foreground - #839496 - - - - name - SublimeLinter Warning Underline - scope - sublimelinter.underline.warning - settings - - background - #b58900 - - - - name - SublimeLinter Violation Outline - scope - sublimelinter.outline.violation - settings - - background - #657b83 - foreground - #657b83 - - - - name - SublimeLinter Violation Underline - scope - sublimelinter.underline.violation - settings - - background - #cb4b16 - - - - name - SublimeBracketHighlighter - scope - brackethighlighter.all - settings - - background - #002b36 - foreground - #cb4b16 - - - - uuid - A4299D9B-1DE5-4BC4-87F6-A757E71B1597 - - diff --git a/src/themes/solarized_light.tmTheme b/src/themes/solarized_light.tmTheme deleted file mode 100644 index 0b4835d4..00000000 --- a/src/themes/solarized_light.tmTheme +++ /dev/null @@ -1,2026 +0,0 @@ - - - - - name - Solarized Light - settings - - - settings - - background - #FDF6E3 - caret - #657B83 - foreground - #657B83 - invisibles - #EEE8D5 - lineHighlight - #EEE8D5 - selection - #073642 - - - - name - Comment - scope - comment - settings - - fontStyle - - foreground - #93A1A1 - - - - name - String - scope - string - settings - - foreground - #2AA198 - - - - name - StringNumber - scope - string - settings - - foreground - #586E75 - - - - name - Regexp - scope - string.regexp - settings - - foreground - #DC322F - - - - name - Number - scope - constant.numeric - settings - - foreground - #D33682 - - - - name - Variable - scope - variable.language, variable.other - settings - - foreground - #268BD2 - - - - name - Keyword - scope - keyword - settings - - foreground - #859900 - - - - name - Storage - scope - storage - settings - - fontStyle - - foreground - #859900 - - - - name - Class name - scope - entity.name.class, entity.name.type.class - settings - - foreground - #268BD2 - - - - name - Function name - scope - entity.name.function - settings - - foreground - #268BD2 - - - - name - Variable start - scope - punctuation.definition.variable - settings - - foreground - #859900 - - - - name - Embedded code markers - scope - punctuation.section.embedded.begin, punctuation.section.embedded.end - settings - - foreground - #DC322F - - - - name - Built-in constant - scope - constant.language, meta.preprocessor - settings - - foreground - #B58900 - - - - name - Support.construct - scope - support.function.construct, keyword.other.new - settings - - foreground - #DC322F - - - - name - User-defined constant - scope - constant.character, constant.other - settings - - foreground - #CB4B16 - - - - name - Inherited class - scope - entity.other.inherited-class - settings - - - - name - Function argument - scope - variable.parameter - settings - - - - name - Tag name - scope - entity.name.tag - settings - - foreground - #268BD2 - - - - name - Tag start/end - scope - punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end - settings - - foreground - #93A1A1 - - - - name - Tag attribute - scope - entity.other.attribute-name - settings - - foreground - #93A1A1 - - - - name - Library function - scope - support.function - settings - - foreground - #268BD2 - - - - name - Continuation - scope - punctuation.separator.continuation - settings - - foreground - #DC322F - - - - name - Library constant - scope - support.constant - settings - - - - name - Library class/type - scope - support.type, support.class - settings - - foreground - #859900 - - - - name - Library Exception - scope - support.type.exception - settings - - foreground - #CB4B16 - - - - name - Special - scope - keyword.other.special-method - settings - - foreground - #CB4B16 - - - - name - Library variable - scope - support.other.variable - settings - - - - name - Invalid - scope - invalid - settings - - - - name - Quoted String - scope - string.quoted.double, string.quoted.single - settings - - foreground - #2AA198 - - - - name - Quotes - scope - punctuation.definition.string.begin, punctuation.definition.string.end - settings - - foreground - #DC322F - - - - name - CSS: Property name (body) - scope - entity.name.tag.css, support.type.property-name.css, meta.property-name.css, support.type.property-name.scss - settings - - fontStyle - - foreground - #657B83 - - - - name - CSS: @ rules (purple) - scope - punctuation.definition.keyword.scss, punctuation.definition.keyword.css, keyword.control.at-rule.charset.css, keyword.control.at-rule.charset.scss, keyword.control.each.css, keyword.control.each.scss, keyword.control.else.css, keyword.control.else.scss, keyword.control.at-rule.import.css, keyword.control.at-rule.import.scss, keyword.control.at-rule.fontface.css, keyword.control.at-rule.fontface.scss, keyword.control.for.css, keyword.control.for.scss, keyword.control.at-rule.function.css, keyword.control.at-rule.function.scss, keyword.control.if.css, keyword.control.if.scss, keyword.control.at-rule.include.scss, keyword.control.at-rule.media.css, keyword.control.at-rule.media.scss, keyword.control.at-rule.font-face.css, keyword.control.at-rule.font-face.scss, meta.at-rule.import.css, variable.other.less, variable.declaration.less, variable.interpolation.less, meta.at-rule.media.scss - settings - - foreground - #6C71c4 - - - - name - CSS: Numeric Value (blue) - scope - constant.numeric.css, keyword.other.unit.css, keyword.unit.css, constant.other.color.rgb-value.css, constant.numeric.scss, constant.other.color.rgb-value.scss, keyword.other.unit.scss, punctuation.definition.constant.scss, punctuation.definition.constant.css, constant.other.rgb-value.css - settings - - fontStyle - - foreground - #268BD2 - - - - name - CSS: String, value and constants (azure) - scope - variable.parameter.url.scss, meta.property-value.css, meta.property-value.scss, support.constant.property-value.scss, support.constant.font-name.scss, string.quoted.single.css, string.quoted.double.css, constant.character.escaped.css, string.quoted.variable.parameter.url, punctuation.definition.string.begin.scss, punctuation.definition.string.begin.css, punctuation.definition.string.end.scss, punctuation.definition.string.end.css, support.constant.property-value.css - settings - - fontStyle - - foreground - #2AA198 - - - - name - CSS: !Important (red) - scope - keyword.other.important.css - settings - - foreground - #DC322F - - - - name - CSS: Standard color value (orange) - scope - support.constant.color, invalid.deprecated.color.w3c-non-standard-color-name.scss - settings - - foreground - #CB4b16 - - - - name - CSS: : , () (body) - scope - punctuation.terminator.rule.css, punctuation.section.function.css, punctuation.section.function.scss, punctuation.separator.key-value.csspunctuation.scss, punctuation.css, keyword.operator.less, entity.name.tag.wildcard.scss, entity.name.tag.wildcard.css, entity.name.tag.reference.scss - settings - - fontStyle - - foreground - #657B83 - - - - name - CSS: Selector > [] and non-spec tags (body) - scope - meta.selector.css - settings - - fontStyle - - foreground - #657B83 - - - - name - CSS: Tag (green) - scope - entity.name.tag.css, entity.name.tag.scss - settings - - fontStyle - - foreground - #859900 - - - - name - CSS .class (yellow) - scope - entity.other.attribute-name.class.css, entity.other.less.mixin - settings - - fontStyle - - foreground - #B58900 - - - - name - CSS: #id (yellow) - scope - source.css entity.other.attribute-name.id - settings - - foreground - #B58900 - - - - name - CSS :pseudo (orange) - scope - entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css - settings - - fontStyle - - foreground - #CB4B16 - - - - name - SCSS: Variables (pink) - scope - variable, variable.scss - settings - - foreground - #D33682 - - - - name - JS: Function Name - scope - meta.function.js, entity.name.function.js, support.function.dom.js - settings - - foreground - #B58900 - - - - name - JS: Source - scope - text.html.basic source.js.embedded.html - settings - - fontStyle - - foreground - #B58900 - - - - name - JS: Function - scope - storage.type.function.js - settings - - foreground - #268BD2 - - - - name - JS: Numeric Constant - scope - constant.numeric.js - settings - - foreground - #2AA198 - - - - name - JS: [] - scope - meta.brace.square.js - settings - - foreground - #268BD2 - - - - name - JS: Storage Type - scope - storage.type.js - settings - - foreground - #268BD2 - - - - name - () - scope - meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js - settings - - foreground - #93A1A1 - - - - name - {} - scope - meta.brace.curly.js - settings - - foreground - #657B83 - - - - name - HTML: Doctype - scope - entity.name.tag.doctype.html, meta.tag.sgml.html, string.quoted.double.doctype.identifiers-and-DTDs.html - settings - - fontStyle - italic - foreground - #839496 - - - - name - HTML: Comment Block - scope - comment.block.html - settings - - fontStyle - italic - foreground - #839496 - - - - name - HTML: Script - scope - entity.name.tag.script.html - settings - - fontStyle - italic - - - - name - HTML: Style - scope - source.css.embedded.html string.quoted.double.html - settings - - fontStyle - - foreground - #2AA198 - - - - name - HTML: Text - scope - text.html.ruby - settings - - foreground - #657b83 - - - - name - HTML: = - scope - text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html - settings - - fontStyle - - foreground - #657B83 - - - - name - HTML: something= - scope - text.html.basic entity.other.attribute-name.html - settings - - foreground - #657B83 - - - - name - HTML: " - scope - text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html, punctuation.definition.string.begin.html, punctuation.definition.string.end.html - settings - - fontStyle - - foreground - #2AA198 - - - - name - HTML: <tag> - scope - entity.name.tag.block.any.html - settings - - foreground - #268BD2 - - - - name - HTML: style - scope - source.css.embedded.html entity.name.tag.style.html - settings - - fontStyle - italic - - - - name - HTML: <style> - scope - entity.name.tag.style.html - settings - - fontStyle - - - - - name - HTML: {} - scope - text.html.basic, punctuation.section.property-list.css - settings - - fontStyle - - - - - name - HTML: Embeddable - scope - source.css.embedded.html, comment.block.html - settings - - fontStyle - italic - foreground - #839496 - - - - name - Ruby: Variable definition - scope - punctuation.definition.variable.ruby - settings - - fontStyle - - foreground - #268BD2 - - - - name - Ruby: Function Name - scope - meta.function.method.with-arguments.ruby - settings - - foreground - #657B83 - - - - name - Ruby: Variable - scope - variable.language.ruby - settings - - foreground - #2AA198 - - - - name - Ruby: Function - scope - entity.name.function.ruby - settings - - foreground - #268BD2 - - - - name - Ruby: Keyword Control - scope - keyword.control.ruby, keyword.control.def.ruby - settings - - foreground - #859900 - - - - name - Ruby: Class - scope - keyword.control.class.ruby, meta.class.ruby - settings - - foreground - #859900 - - - - name - Ruby: Class Name - scope - entity.name.type.class.ruby - settings - - fontStyle - - foreground - #B58900 - - - - name - Ruby: Keyword - scope - keyword.control.ruby - settings - - fontStyle - - foreground - #859900 - - - - name - Ruby: Support Class - scope - support.class.ruby - settings - - fontStyle - - foreground - #B58900 - - - - name - Ruby: Special Method - scope - keyword.other.special-method.ruby - settings - - foreground - #859900 - - - - name - Ruby: Constant - scope - constant.language.ruby, constant.numeric.ruby - settings - - foreground - #2AA198 - - - - name - Ruby: Constant Other - scope - variable.other.constant.ruby - settings - - fontStyle - - foreground - #B58900 - - - - name - Ruby: :symbol - scope - constant.other.symbol.ruby - settings - - fontStyle - - foreground - #2AA198 - - - - name - Ruby: Punctuation Section '' - scope - punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby - settings - - foreground - #DC322F - - - - name - Ruby: Special Method - scope - keyword.other.special-method.ruby - settings - - foreground - #CB4B16 - - - - name - PHP: Include - scope - keyword.control.import.include.php - settings - - foreground - #CB4B16 - - - - name - Ruby: erb = - scope - text.html.ruby meta.tag.inline.any.html - settings - - fontStyle - - foreground - #839496 - - - - name - Ruby: erb "" - scope - text.html.ruby punctuation.definition.string.begin, text.html.ruby punctuation.definition.string.end - settings - - fontStyle - - foreground - #2AA198 - - - - name - PHP: Quoted Single - scope - punctuation.definition.string.begin, punctuation.definition.string.end - settings - - foreground - #839496 - - - - name - PHP: Class Names - scope - support.class.php - settings - - foreground - #586E75 - - - - name - PHP: [] - scope - keyword.operator.index-start.php, keyword.operator.index-end.php - settings - - foreground - #DC322F - - - - name - PHP: Array - scope - meta.array.php - settings - - foreground - #586E75 - - - - name - PHP: Array() - scope - meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php - settings - - fontStyle - - foreground - #B58900 - - - - name - PHP: Array Construct - scope - support.function.construct.php - settings - - foreground - #B58900 - - - - name - PHP: Array Begin - scope - punctuation.definition.array.begin, punctuation.definition.array.end - settings - - foreground - #DC322F - - - - name - PHP: Numeric Constant - scope - constant.numeric.php - settings - - foreground - #2AA198 - - - - name - PHP: New - scope - keyword.other.new.php - settings - - foreground - #CB4B16 - - - - name - PHP: :: - scope - keyword.operator.class - settings - - fontStyle - - foreground - #586E75 - - - - name - PHP: Other Property - scope - variable.other.property.php - settings - - foreground - #839496 - - - - name - PHP: Class - scope - storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php - settings - - foreground - #B58900 - - - - name - PHP: Semicolon - scope - punctuation.terminator.expression.php - settings - - foreground - #657B83 - - - - name - PHP: Inherited Class - scope - meta.other.inherited-class.php - settings - - fontStyle - - foreground - #586E75 - - - - name - PHP: Storage Type - scope - storage.type.php - settings - - foreground - #859900 - - - - name - PHP: Function - scope - entity.name.function.php - settings - - foreground - #839496 - - - - name - PHP: Function Construct - scope - support.function.construct.php - settings - - foreground - #859900 - - - - name - PHP: Function Call - scope - entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php - settings - - foreground - #839496 - - - - name - PHP: Comment - scope - keyword.other.phpdoc - settings - - fontStyle - - foreground - #839496 - - - - name - PHP: Source Emebedded - scope - source.php.embedded.block.html - settings - - foreground - #CB4B16 - - - - name - PHP: Storage Type Function - scope - storage.type.function.php - settings - - foreground - #CB4B16 - - - - name - C: constant - scope - constant.numeric.c - settings - - fontStyle - - foreground - #2AA198 - - - - name - C: Meta Preprocessor - scope - meta.preprocessor.c.include, meta.preprocessor.macro.c - settings - - fontStyle - - foreground - #CB4B16 - - - - name - C: Keyword - scope - keyword.control.import.define.c, keyword.control.import.include.c - settings - - fontStyle - - foreground - #CB4B16 - - - - name - C: Function Preprocessor - scope - entity.name.function.preprocessor.c - settings - - fontStyle - - foreground - #CB4B16 - - - - name - C: include <something.c> - scope - meta.preprocessor.c.include string.quoted.other.lt-gt.include.c, meta.preprocessor.c.include punctuation.definition.string.begin.c, meta.preprocessor.c.include punctuation.definition.string.end.c - settings - - fontStyle - - foreground - #2AA198 - - - - name - C: Function - scope - support.function.C99.c, support.function.any-method.c, entity.name.function.c - settings - - fontStyle - - foreground - #586E75 - - - - name - C: " - scope - punctuation.definition.string.begin.c, punctuation.definition.string.end.c - settings - - fontStyle - - foreground - #2AA198 - - - - name - C: Storage Type - scope - storage.type.c - settings - - fontStyle - - foreground - #B58900 - - - - name - diff: header - scope - meta.diff, meta.diff.header - settings - - background - #B58900 - fontStyle - italic - foreground - #EEE8D5 - - - - name - diff: deleted - scope - markup.deleted - settings - - background - #EEE8D5 - fontStyle - - foreground - #DC322F - - - - name - diff: changed - scope - markup.changed - settings - - background - #EEE8D5 - fontStyle - - foreground - #CB4B16 - - - - name - diff: inserted - scope - markup.inserted - settings - - background - #EEE8D5 - foreground - #2AA198 - - - - name - reST raw - scope - text.restructuredtext markup.raw - settings - - foreground - #2AA198 - - - - name - Other: Removal - scope - other.package.exclude, other.remove - settings - - fontStyle - - foreground - #DC322F - - - - name - Other: Add - scope - other.add - settings - - foreground - #2AA198 - - - - name - Tex: {} - scope - punctuation.section.group.tex , punctuation.definition.arguments.begin.latex, punctuation.definition.arguments.end.latex, punctuation.definition.arguments.latex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: {text} - scope - meta.group.braces.tex - settings - - fontStyle - - foreground - #B58900 - - - - name - Tex: Other Math - scope - string.other.math.tex - settings - - fontStyle - - foreground - #B58900 - - - - name - Tex: {var} - scope - variable.parameter.function.latex - settings - - fontStyle - - foreground - #CB4B16 - - - - name - Tex: Math \\ - scope - punctuation.definition.constant.math.tex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: Constant Math - scope - text.tex.latex constant.other.math.tex, constant.other.general.math.tex, constant.other.general.math.tex, constant.character.math.tex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Tex: Other Math String - scope - string.other.math.tex - settings - - fontStyle - - foreground - #B58900 - - - - name - Tex: $ - scope - punctuation.definition.string.begin.tex, punctuation.definition.string.end.tex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: \label - scope - keyword.control.label.latex, text.tex.latex constant.other.general.math.tex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Tex: \label { } - scope - variable.parameter.definition.label.latex - settings - - fontStyle - - foreground - #DC322F - - - - name - Tex: Function - scope - support.function.be.latex - settings - - fontStyle - - foreground - #859900 - - - - name - Tex: Support Function Section - scope - support.function.section.latex - settings - - fontStyle - - foreground - #CB4B16 - - - - name - Tex: Support Function - scope - support.function.general.tex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Tex: Comment - scope - punctuation.definition.comment.tex, comment.line.percentage.tex - settings - - fontStyle - italic - - - - name - Tex: Reference Label - scope - keyword.control.ref.latex - settings - - fontStyle - - foreground - #2AA198 - - - - name - Python: storage - scope - storage.type.class.python, storage.type.function.python, storage.modifier.global.python - settings - - fontStyle - - foreground - #859900 - - - - name - Python: import - scope - keyword.control.import.python, keyword.control.import.from.python - settings - - foreground - #CB4B16 - - - - name - Python: Support.exception - scope - support.type.exception.python - settings - - foreground - #B58900 - - - - name - Shell: builtin - scope - support.function.builtin.shell - settings - - foreground - #859900 - - - - name - Shell: variable - scope - variable.other.normal.shell - settings - - foreground - #CB4B16 - - - - name - Shell: DOT_FILES - scope - source.shell - settings - - fontStyle - - foreground - #268BD2 - - - - name - Shell: meta scope in loop - scope - meta.scope.for-in-loop.shell, variable.other.loop.shell - settings - - fontStyle - - foreground - #586E75 - - - - name - Shell: "" - scope - punctuation.definition.string.end.shell, punctuation.definition.string.begin.shell - settings - - fontStyle - - foreground - #859900 - - - - name - Shell: Meta Block - scope - meta.scope.case-block.shell, meta.scope.case-body.shell - settings - - fontStyle - - foreground - #586E75 - - - - name - Shell: [] - scope - punctuation.definition.logical-expression.shell - settings - - fontStyle - - foreground - #DC322F - - - - name - Shell: Comment - scope - comment.line.number-sign.shell - settings - - fontStyle - italic - - - - name - Java: import - scope - keyword.other.import.java - settings - - fontStyle - - foreground - #CB4B16 - - - - name - Java: meta-import - scope - storage.modifier.import.java - settings - - fontStyle - - foreground - #586E75 - - - - name - Java: Class - scope - meta.class.java storage.modifier.java - settings - - fontStyle - - foreground - #B58900 - - - - name - Java: /* comment */ - scope - source.java comment.block - settings - - fontStyle - - foreground - #586E75 - - - - name - Java: /* @param */ - scope - comment.block meta.documentation.tag.param.javadoc keyword.other.documentation.param.javadoc - settings - - fontStyle - - foreground - #586E75 - - - - name - Perl: variables - scope - punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl - settings - - foreground - #B58900 - - - - name - Perl: functions - scope - support.function.perl - settings - - foreground - #859900 - - - - name - Perl: comments - scope - comment.line.number-sign.perl - settings - - fontStyle - italic - foreground - #586E75 - - - - name - Perl: quotes - scope - punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl - settings - - foreground - #2AA198 - - - - name - Perl: \char - scope - constant.character.escape.perl - settings - - foreground - #DC322F - - - - Name - Markdown punctuation - scope - markup.list, text.html.markdown punctuation.definition, meta.separator.markdown - settings - - foreground - #CB4b16 - - - - Name - Markdown heading - scope - markup.heading - settings - - foreground - #268BD2 - - - - Name - Markdown text inside some block element - scope - markup.quote, meta.paragraph.list - settings - - foreground - #2AA198 - - - - Name - Markdown em - scope - markup.italic - settings - - fontStyle - italic - - - - Name - Markdown strong - scope - markup.bold - settings - - fontStyle - bold - - - - Name - Markdown reference - scope - markup.underline.link.markdown, meta.link.inline punctuation.definition.metadata, meta.link.reference.markdown punctuation.definition.constant, meta.link.reference.markdown constant.other.reference - settings - - foreground - #B58900 - - - - Name - Markdown linebreak - scope - meta.paragraph.markdown meta.dummy.line-break - settings - - background - #6C71c4 - - - - name - SublimeLinter Annotations - scope - sublimelinter.notes - settings - - background - #eee8d5 - foreground - #eee8d5 - - - - name - SublimeLinter Error Outline - scope - sublimelinter.outline.illegal - settings - - background - #93a1a1 - foreground - #93a1a1 - - - - name - SublimeLinter Error Underline - scope - sublimelinter.underline.illegal - settings - - background - #dc322f - - - - name - SublimeLinter Warning Outline - scope - sublimelinter.outline.warning - settings - - background - #839496 - foreground - #839496 - - - - name - SublimeLinter Warning Underline - scope - sublimelinter.underline.warning - settings - - background - #b58900 - - - - name - SublimeLinter Violation Outline - scope - sublimelinter.outline.violation - settings - - background - #657b83 - foreground - #657b83 - - - - name - SublimeLinter Violation Underline - scope - sublimelinter.underline.violation - settings - - background - #cb4b16 - - - - name - SublimeBracketHighlighter - scope - brackethighlighter.all - settings - - background - #FDF6E3 - foreground - #cb4b16 - - - - uuid - 38E819D9-AE02-452F-9231-ECC3B204AFD7 - - diff --git a/src/view/mod.rs b/src/view/mod.rs index a2fed5d1..705a0192 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -28,6 +28,7 @@ use std::cell::RefCell; use std::cmp; use std::collections::HashMap; use std::ops::Drop; +use std::path::PathBuf; use std::process::Command; use std::rc::Rc; use std::sync::mpsc::{self, Sender, SyncSender}; @@ -53,7 +54,7 @@ impl View { event_channel: Sender, ) -> Result { let terminal = build_terminal().context("Failed to initialize terminal")?; - let theme_path = preferences.borrow().theme_path()?; + let theme_path = user_theme_path()?; let theme_set = ThemeLoader::new(theme_path).load()?; let (killswitch_tx, killswitch_rx) = mpsc::sync_channel(0); @@ -196,6 +197,16 @@ impl View { } } +#[cfg(not(test))] +fn user_theme_path() -> Result { + Preferences::theme_path() +} + +#[cfg(test)] +fn user_theme_path() -> Result { + Ok(PathBuf::from("tests/fixtures/user_themes")) +} + impl Drop for View { fn drop(&mut self) { debug!("drop triggered; killing event listener"); @@ -223,6 +234,15 @@ mod tests { use std::sync::mpsc; use syntect::highlighting::{Highlighter, ThemeSet}; + #[test] + fn new_populates_theme_set_via_theme_loader() { + let preferences = Rc::new(RefCell::new(Preferences::new(None))); + let (tx, _) = mpsc::channel(); + let view = View::new(preferences, tx).unwrap(); + + assert!(view.theme_set.themes.contains_key("fixture_theme")); + } + #[test] fn scroll_down_prevents_scrolling_completely_beyond_buffer() { let preferences = Rc::new(RefCell::new(Preferences::new(None))); diff --git a/src/view/theme_loader.rs b/src/view/theme_loader.rs index b82f6d42..f0464096 100644 --- a/src/view/theme_loader.rs +++ b/src/view/theme_loader.rs @@ -2,8 +2,9 @@ use crate::errors::*; use std::collections::BTreeMap; use std::ffi::OsStr; use std::fs::File; -use std::io::{BufReader, Cursor, Read, Seek}; +use std::io::{BufReader, Read, Seek}; use std::path::PathBuf; +use syntect::dumps::from_uncompressed_data; use syntect::highlighting::{Theme, ThemeSet}; pub struct ThemeLoader { @@ -30,6 +31,10 @@ impl ThemeLoader { } fn load_user(&mut self) -> Result<()> { + if !self.path.is_dir() { + return Ok(()); + } + let theme_dir_entries = self .path .read_dir() @@ -55,14 +60,14 @@ impl ThemeLoader { } fn load_defaults(&mut self) -> Result<()> { - self.insert_theme( - "solarized_dark", - Cursor::new(include_str!("../themes/solarized_dark.tmTheme")), - )?; - self.insert_theme( - "solarized_light", - Cursor::new(include_str!("../themes/solarized_light.tmTheme")), - )?; + self.themes.extend( + from_uncompressed_data::(include_bytes!(concat!( + env!("OUT_DIR"), + "/app_themes.packdump" + ))) + .context("Couldn't load bundled themes")? + .themes, + ); Ok(()) } @@ -78,3 +83,29 @@ impl ThemeLoader { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::ThemeLoader; + use std::path::PathBuf; + + #[test] + fn load_includes_bundled_and_fixture_themes() { + let theme_set = ThemeLoader::new(PathBuf::from("tests/fixtures/user_themes")) + .load() + .unwrap(); + + assert!(theme_set.themes.contains_key("solarized_dark")); + assert!(theme_set.themes.contains_key("fixture_theme")); + } + + #[test] + fn load_ignores_missing_user_theme_directory() { + let missing_path = PathBuf::from("tests/fixtures/missing_themes"); + assert!(!missing_path.exists()); + + let theme_set = ThemeLoader::new(missing_path).load().unwrap(); + + assert!(theme_set.themes.contains_key("solarized_dark")); + } +} diff --git a/tests/fixtures/user_themes/fixture_theme.tmTheme b/tests/fixtures/user_themes/fixture_theme.tmTheme new file mode 100644 index 00000000..52b63b38 --- /dev/null +++ b/tests/fixtures/user_themes/fixture_theme.tmTheme @@ -0,0 +1,22 @@ + + + + + name + Fixture Theme + settings + + + settings + + foreground + #f8f4e3 + background + #101820 + line_highlight + #2f3e46 + + + + + diff --git a/tests/theme_compiler.rs b/tests/theme_compiler.rs new file mode 100644 index 00000000..c9d54ba5 --- /dev/null +++ b/tests/theme_compiler.rs @@ -0,0 +1,312 @@ +#[path = "../build/theme_compiler/mod.rs"] +mod theme_compiler; + +use std::fs; +use std::io::Cursor; +use std::path::PathBuf; +use std::time::{SystemTime, UNIX_EPOCH}; + +use syntect::highlighting::{FontStyle, ThemeSet}; + +fn load_rendered_theme(theme: &theme_compiler::Theme) -> syntect::highlighting::Theme { + let rendered = theme_compiler::render_tmtheme(theme); + let mut cursor = Cursor::new(rendered.into_bytes()); + ThemeSet::load_from_reader(&mut cursor).unwrap() +} + +#[test] +fn parse_theme_resolves_palette_references() { + let theme = theme_compiler::parse_theme( + r##" +name: Test Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - name: Comment + scope: comment + foreground: fg +"##, + ) + .unwrap(); + + assert_eq!(theme.settings.foreground, "#112233"); + assert_eq!(theme.settings.background, "#445566"); + assert_eq!(theme.settings.line_highlight, "#778899"); + assert_eq!(theme.rules[0].foreground.as_deref(), Some("#112233")); +} + +#[test] +fn parse_theme_rejects_unknown_keys() { + let error = theme_compiler::parse_theme( + r##" +name: Bad Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" + selection_color: "#000000" +settings: + foreground: fg + background: bg + line_highlight: line + selection: selection_color +rules: + - scope: comment + foreground: fg +"##, + ) + .unwrap_err(); + + assert!(error.contains("selection")); +} + +#[test] +fn parse_theme_rejects_invalid_rule_color_reference() { + let error = theme_compiler::parse_theme( + r##" +name: Bad Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - scope: comment + foreground: missing +"##, + ) + .unwrap_err(); + + assert!(error.contains("unknown palette key: missing")); +} + +#[test] +fn parse_theme_rejects_literal_colors_outside_palette() { + let error = theme_compiler::parse_theme( + r##" +name: Bad Theme +palette: + bg: "#445566" + line: "#778899" +settings: + foreground: "#112233" + background: bg + line_highlight: line +rules: + - scope: comment + foreground: bg +"##, + ) + .unwrap_err(); + + assert!(error.contains("must reference a palette key")); + assert!(error.contains("literal colors belong in palette")); +} + +#[test] +fn parse_theme_rejects_non_string_scope() { + let error = theme_compiler::parse_theme( + r##" +name: Bad Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - scope: [comment] + foreground: fg +"##, + ) + .unwrap_err(); + + assert!(error.contains("invalid type")); + assert!(error.contains("sequence")); +} + +#[test] +fn parse_theme_preserves_font_style() { + let theme = theme_compiler::parse_theme( + r##" +name: Test Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - name: Comment + scope: comment + foreground: fg + font_style: [italic] +"##, + ) + .unwrap(); + + assert_eq!(theme.rules[0].font_style, Some(vec!["italic".to_string()])); +} + +#[test] +fn parse_theme_preserves_empty_font_style() { + let theme = theme_compiler::parse_theme( + r##" +name: Test Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - scope: comment + foreground: fg + font_style: [] +"##, + ) + .unwrap(); + + assert_eq!(theme.rules[0].font_style, Some(Vec::new())); +} + +#[test] +fn render_tmtheme_is_parseable() { + let theme = theme_compiler::parse_theme( + r##" +name: Test Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - scope: comment + foreground: fg +"##, + ) + .unwrap(); + + load_rendered_theme(&theme); +} + +#[test] +fn render_tmtheme_preserves_empty_font_style() { + let theme = theme_compiler::parse_theme( + r##" +name: Test Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - scope: comment + foreground: fg + font_style: [] +"##, + ) + .unwrap(); + + let rendered_theme = load_rendered_theme(&theme); + + assert_eq!(rendered_theme.scopes.len(), 1); + assert_eq!( + rendered_theme.scopes[0].style.font_style, + Some(FontStyle::empty()) + ); +} + +#[test] +fn render_tmtheme_preserves_font_style() { + let theme = theme_compiler::parse_theme( + r##" +name: Test Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - scope: comment + foreground: fg + font_style: [italic, underline] +"##, + ) + .unwrap(); + + let rendered_theme = load_rendered_theme(&theme); + + assert_eq!(rendered_theme.scopes.len(), 1); + assert_eq!( + rendered_theme.scopes[0].style.font_style, + Some(FontStyle::ITALIC | FontStyle::UNDERLINE) + ); +} + +#[test] +fn compile_themes_writes_generated_tmtheme_files() { + let unique = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_nanos(); + let base = std::env::temp_dir().join(format!("amp-theme-compiler-{unique}")); + let source_dir = base.join("source"); + let output_dir = base.join("output"); + fs::create_dir_all(&source_dir).unwrap(); + + fs::write( + source_dir.join("sample.yml"), + r##" +name: Sample Theme +palette: + fg: "#112233" + bg: "#445566" + line: "#778899" +settings: + foreground: fg + background: bg + line_highlight: line +rules: + - scope: comment + foreground: fg +"##, + ) + .unwrap(); + + let outputs = theme_compiler::compile_themes(&source_dir, &output_dir).unwrap(); + assert_eq!( + outputs, + vec![PathBuf::from(output_dir.join("sample.tmTheme"))] + ); + + let file = fs::File::open(output_dir.join("sample.tmTheme")).unwrap(); + let mut reader = std::io::BufReader::new(file); + ThemeSet::load_from_reader(&mut reader).unwrap(); + + fs::remove_dir_all(base).unwrap(); +} diff --git a/themes/monokai_extended.yml b/themes/monokai_extended.yml new file mode 100644 index 00000000..b053afd4 --- /dev/null +++ b/themes/monokai_extended.yml @@ -0,0 +1,86 @@ +name: Monokai Extended +palette: + foreground: "#F8F8F2" + background: "#222222" + line: "#333333" + comment: "#75715E" + string: "#E6DB74" + escape: "#F6AA11" + number: "#BE84FF" + keyword: "#F92672" + function: "#A6E22E" + type: "#66D9EF" + variable: "#F4F1DE" + parameter: "#FD971F" + punctuation: "#908F88" + white: "#FFFFFF" +settings: + foreground: foreground + background: background + line_highlight: line +rules: + - name: Comments + scope: "comment, comment.block.documentation, punctuation.definition.comment" + foreground: comment + font_style: [italic] + - name: Strings + scope: "string, string.quoted, string.unquoted" + foreground: string + - name: String Escapes and Regex + scope: "constant.character.escape, constant.other.escape, string.regexp, punctuation.definition.string" + foreground: escape + - name: Numbers + scope: constant.numeric + foreground: number + - name: Constants + scope: "constant.language, constant.character, constant.other, support.constant" + foreground: number + - name: Keywords + scope: "keyword, keyword.control, keyword.declaration, keyword.other, punctuation.definition.keyword" + foreground: keyword + - name: Storage and Modifiers + scope: "storage, storage.type, storage.modifier" + foreground: keyword + - name: Function Names + scope: "entity.name.function, variable.function" + foreground: function + - name: Function Calls and Builtins + scope: "meta.function-call, support.function, support.function.builtin, support.macro" + foreground: type + - name: Types + scope: "entity.name.type, entity.name.class, entity.name.struct, entity.name.enum, entity.name.trait, support.type, support.class" + foreground: type + - name: Namespaces and Modules + scope: "entity.name.namespace, entity.name.module, support.module" + foreground: type + - name: Macros and Preprocessor + scope: "entity.name.macro, meta.preprocessor" + foreground: number + - name: Local Variables + scope: "variable.other, variable.object, variable.other.member" + foreground: variable + - name: Parameters + scope: variable.parameter + foreground: parameter + - name: Language Variables + scope: "variable.language, support.variable" + foreground: white + - name: Attributes and Annotations + scope: "entity.other.attribute-name, storage.annotation, punctuation.definition.annotation" + foreground: function + - name: Semantic Operators + scope: "keyword.operator, keyword.operator.assignment, keyword.operator.accessor, keyword.operator.range" + foreground: keyword + - name: Structural Punctuation + scope: "punctuation.separator, punctuation.terminator, punctuation.section, meta.brace, meta.delimiter" + foreground: punctuation + - name: Tags + scope: "entity.name.tag, meta.tag, punctuation.definition.tag" + foreground: keyword + - name: Markup and Diff + scope: "markup.heading, markup.bold, markup.italic, markup.inserted, markup.deleted, markup.changed" + foreground: function + - name: Invalid + scope: "invalid, invalid.deprecated" + foreground: foreground + background: keyword diff --git a/themes/solarized_dark.yml b/themes/solarized_dark.yml new file mode 100644 index 00000000..abf336e7 --- /dev/null +++ b/themes/solarized_dark.yml @@ -0,0 +1,110 @@ +name: Solarized Dark +palette: + base3: "#002B36" + base2: "#073642" + base1: "#586E75" + base0: "#657B83" + base00: "#839496" + base01: "#93A1A1" + base02: "#b2b2b2" + base3_light: "#EEE8D5" + line: "#303030" + yellow: "#B58900" + orange: "#CB4B16" + red: "#DC322F" + magenta: "#D33682" + violet: "#6C71C4" + blue: "#268BD2" + cyan: "#2AA198" + green: "#859900" +settings: + foreground: base02 + background: base3 + line_highlight: line +rules: + - name: Comment + scope: "comment, comment.block.documentation, punctuation.definition.comment" + foreground: base1 + font_style: [] + - name: String + scope: "string, string.quoted.double, string.quoted.single" + foreground: cyan + - name: Regexp + scope: "string.regexp, constant.character.escape, punctuation.definition.string.begin, punctuation.definition.string.end" + foreground: red + - name: Number + scope: constant.numeric + foreground: magenta + - name: Variable + scope: "variable.language, variable.other" + foreground: blue + - name: Keyword + scope: "keyword, keyword.control" + foreground: green + - name: Storage + scope: "storage, storage.type.class.python, storage.type.function.python, storage.modifier.global.python" + foreground: green + font_style: [] + - name: Functions + scope: "entity.name.function, support.function, support.function.builtin.shell, meta.function.js, entity.name.function.js" + foreground: blue + - name: Support Constructs + scope: "support.function.construct, keyword.other.new, support.function.construct.php" + foreground: red + - name: Types + scope: "entity.name.class, entity.name.type.class, entity.name.type, support.type.exception, support.class" + foreground: blue + - name: Support Types + scope: "support.type, storage.type.c, storage.type.js, storage.type.php" + foreground: green + - name: Built-in Constant + scope: "constant.language, meta.preprocessor, keyword.control.import.define.c, keyword.control.import.include.c" + foreground: yellow + - name: User-defined Constant + scope: "constant.character, constant.other, keyword.other.special-method, keyword.control.import.include.php" + foreground: orange + - name: Parameters + scope: "variable.parameter, variable.parameter.function.latex, variable.parameter.definition.label.latex" + foreground: orange + - name: Operators + scope: "keyword.operator, punctuation.separator.continuation, punctuation.definition.array.begin, punctuation.definition.array.end" + foreground: red + - name: Structural Punctuation + scope: "punctuation.separator, punctuation.terminator, punctuation.section, meta.brace, meta.delimiter" + foreground: base0 + - name: Tags + scope: "entity.name.tag, punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end" + foreground: blue + - name: Attributes + scope: "entity.other.attribute-name, entity.other.attribute-name.class.css, entity.other.attribute-name.id, entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css" + foreground: base01 + - name: Markup + scope: "markup.heading, markup.quote, markup.list, meta.separator.markdown" + foreground: blue + - name: Diff Deleted + scope: "markup.deleted, markup.deleted.git_gutter" + foreground: red + background: base3_light + font_style: [] + - name: Diff Changed + scope: "markup.changed, markup.changed.git_gutter" + foreground: orange + background: base3_light + font_style: [] + - name: Diff Inserted + scope: "markup.inserted, markup.inserted.git_gutter, other.add" + foreground: cyan + background: base3_light + - name: Invalid + scope: "invalid, invalid.deprecated, sublimelinter.underline.illegal" + foreground: base3_light + background: red + - name: Underline Warning + scope: "sublimelinter.underline.warning, sublimelinter.underline.violation" + background: yellow + - name: Tex Functions + scope: "support.function.be.latex, support.function.section.latex, support.function.general.tex, keyword.control.ref.latex, keyword.control.label.latex" + foreground: cyan + - name: Markdown Styles + scope: "markup.italic, markup.bold, markup.underline.link.markdown, meta.link.reference.markdown constant.other.reference" + foreground: yellow diff --git a/themes/solarized_light.yml b/themes/solarized_light.yml new file mode 100644 index 00000000..0a238e19 --- /dev/null +++ b/themes/solarized_light.yml @@ -0,0 +1,106 @@ +name: Solarized Light +palette: + base3: "#FDF6E3" + base2: "#EEE8D5" + base1: "#93A1A1" + base0: "#839496" + body: "#657B83" + yellow: "#B58900" + orange: "#CB4B16" + red: "#DC322F" + magenta: "#D33682" + violet: "#6C71C4" + blue: "#268BD2" + cyan: "#2AA198" + green: "#859900" +settings: + foreground: body + background: base3 + line_highlight: base2 +rules: + - name: Comment + scope: "comment, comment.block.documentation, punctuation.definition.comment" + foreground: base1 + font_style: [] + - name: String + scope: "string, string.quoted.double, string.quoted.single" + foreground: cyan + - name: Regexp + scope: "string.regexp, constant.character.escape, punctuation.definition.string.begin, punctuation.definition.string.end" + foreground: red + - name: Number + scope: constant.numeric + foreground: magenta + - name: Variable + scope: "variable.language, variable.other" + foreground: blue + - name: Keyword + scope: "keyword, keyword.control" + foreground: green + - name: Storage + scope: "storage, storage.type.class.python, storage.type.function.python, storage.modifier.global.python" + foreground: green + font_style: [] + - name: Functions + scope: "entity.name.function, support.function, support.function.builtin.shell, meta.function.js, entity.name.function.js" + foreground: blue + - name: Support Constructs + scope: "support.function.construct, keyword.other.new, support.function.construct.php" + foreground: red + - name: Types + scope: "entity.name.class, entity.name.type.class, entity.name.type, support.type.exception, support.class" + foreground: blue + - name: Support Types + scope: "support.type, storage.type.c, storage.type.js, storage.type.php" + foreground: green + - name: Built-in Constant + scope: "constant.language, meta.preprocessor, keyword.control.import.define.c, keyword.control.import.include.c" + foreground: yellow + - name: User-defined Constant + scope: "constant.character, constant.other, keyword.other.special-method, keyword.control.import.include.php" + foreground: orange + - name: Parameters + scope: "variable.parameter, variable.parameter.function.latex, variable.parameter.definition.label.latex" + foreground: orange + - name: Operators + scope: "keyword.operator, punctuation.separator.continuation, punctuation.definition.array.begin, punctuation.definition.array.end" + foreground: red + - name: Structural Punctuation + scope: "punctuation.separator, punctuation.terminator, punctuation.section, meta.brace, meta.delimiter" + foreground: body + - name: Tags + scope: "entity.name.tag, punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end" + foreground: blue + - name: Attributes + scope: "entity.other.attribute-name, entity.other.attribute-name.class.css, entity.other.attribute-name.id, entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css" + foreground: base1 + - name: Markup + scope: "markup.heading, markup.quote, markup.list, meta.separator.markdown" + foreground: blue + - name: Diff Deleted + scope: "markup.deleted, markup.deleted.git_gutter" + foreground: red + background: base2 + font_style: [] + - name: Diff Changed + scope: "markup.changed, markup.changed.git_gutter" + foreground: orange + background: base2 + font_style: [] + - name: Diff Inserted + scope: "markup.inserted, markup.inserted.git_gutter, other.add" + foreground: cyan + background: base2 + - name: Invalid + scope: "invalid, invalid.deprecated, sublimelinter.underline.illegal" + foreground: base2 + background: red + - name: Underline Warning + scope: "sublimelinter.underline.warning, sublimelinter.underline.violation" + background: yellow + - name: Tex Functions + scope: "support.function.be.latex, support.function.section.latex, support.function.general.tex, keyword.control.ref.latex, keyword.control.label.latex" + foreground: cyan + - name: Markdown Styles + scope: "markup.italic, markup.bold, markup.underline.link.markdown, meta.link.reference.markdown constant.other.reference" + foreground: yellow