use nu_ansi_term::Color;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
macro_rules! color_prop {
($desc:expr) => {{ $crate::config::colors::make_color_schema($desc, None) }};
($desc:expr, default = $default:expr) => {{ $crate::config::colors::make_color_schema($desc, Some($default)) }};
}
#[doc(hidden)]
pub fn make_color_schema(description: &str, default: Option<&str>) -> schemars::Schema {
let one_of = schemars::json_schema!({
"oneOf": [
{
"type": "string",
"enum": [
"Default", "Black", "Red", "Green", "Yellow", "Blue",
"Purple", "Magenta", "Cyan", "White",
"DarkGray", "LightGray",
"LightRed", "LightGreen", "LightYellow", "LightBlue",
"LightPurple", "LightMagenta", "LightCyan"
]
},
{
"type": "object",
"properties": {
"Fixed": { "type": "integer", "minimum": 0, "maximum": 255 }
},
"required": ["Fixed"],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"Rgb": {
"type": "array",
"items": { "type": "integer", "minimum": 0, "maximum": 255 },
"minItems": 3,
"maxItems": 3
}
},
"required": ["Rgb"],
"additionalProperties": false
}
]
});
let mut schema = one_of;
schema.insert(
"description".to_string(),
serde_json::Value::String(description.to_string()),
);
if let Some(default_val) = default {
schema.insert(
"default".to_string(),
serde_json::Value::String(default_val.to_string()),
);
}
schema
}
pub(crate) use color_prop;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[derive(Default)]
pub struct ColorsConfig {
pub r: RColorConfig,
pub meta: MetaColorConfig,
pub prompt: PromptColorConfig,
}
impl JsonSchema for ColorsConfig {
fn schema_name() -> std::borrow::Cow<'static, str> {
std::borrow::Cow::Borrowed("ColorsConfig")
}
fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
schemars::json_schema!({
"type": "object",
"description": "Color configuration for syntax highlighting and prompts. Colors can be named (e.g., 'Red', 'DarkGray'), 256-color ({ Fixed: 99 }), or RGB ({ Rgb: [255, 0, 0] }).",
"properties": {
"r": {
"type": "object",
"description": "Colors for R syntax tokens",
"properties": {
"comment": color_prop!("Color for comments"),
"string": color_prop!("Color for string literals"),
"number": color_prop!("Color for numeric literals"),
"keyword": color_prop!("Color for keywords"),
"constant": color_prop!("Color for constants (TRUE, FALSE, NULL, NA, etc.)"),
"operator": color_prop!("Color for operators"),
"punctuation": color_prop!("Color for punctuation"),
"identifier": color_prop!("Color for identifiers"),
"matching_bracket": color_prop!("Background color for matching bracket highlighting", default = "LightYellow")
}
},
"meta": {
"type": "object",
"description": "Colors for meta commands",
"properties": {
"command": color_prop!("Color for meta command lines")
}
},
"prompt": {
"type": "object",
"description": "Colors for prompts",
"properties": {
"main": color_prop!("Color for the main R prompt"),
"continuation": color_prop!("Color for the continuation prompt"),
"shell": color_prop!("Color for the shell mode prompt"),
"indicator": color_prop!("Color for the mode indicator text"),
"status": {
"type": "object",
"description": "Colors for command status indicator",
"properties": {
"success": color_prop!("Color for success status"),
"error": color_prop!("Color for error status")
}
},
"duration": color_prop!("Color for command duration indicator", default = "Yellow"),
"vi": {
"type": "object",
"description": "Colors for vi mode indicator",
"properties": {
"insert": color_prop!("Color for vi insert mode"),
"normal": color_prop!("Color for vi normal mode"),
"non_vi": color_prop!("Color for non-vi modes (Emacs, etc.)")
}
}
}
}
}
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct RColorConfig {
pub comment: Color,
pub string: Color,
pub number: Color,
pub keyword: Color,
pub constant: Color,
pub operator: Color,
pub punctuation: Color,
pub identifier: Color,
pub matching_bracket: Color,
}
impl Default for RColorConfig {
fn default() -> Self {
RColorConfig {
comment: Color::DarkGray,
string: Color::Green,
number: Color::LightMagenta,
keyword: Color::LightBlue,
constant: Color::LightCyan,
operator: Color::Yellow,
punctuation: Color::Default,
identifier: Color::Default,
matching_bracket: Color::LightYellow,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct MetaColorConfig {
pub command: Color,
}
impl Default for MetaColorConfig {
fn default() -> Self {
MetaColorConfig {
command: Color::Magenta,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct PromptColorConfig {
pub main: Color,
pub continuation: Color,
pub shell: Color,
pub indicator: Color,
pub status: StatusColorConfig,
pub duration: Color,
pub vi: ViColorConfig,
}
impl Default for PromptColorConfig {
fn default() -> Self {
PromptColorConfig {
main: Color::LightGreen,
continuation: Color::LightGreen,
shell: Color::LightRed,
indicator: Color::Yellow,
status: StatusColorConfig::default(),
duration: Color::Yellow,
vi: ViColorConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct StatusColorConfig {
pub success: Color,
pub error: Color,
}
impl Default for StatusColorConfig {
fn default() -> Self {
StatusColorConfig {
success: Color::LightGreen,
error: Color::LightRed,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct ViColorConfig {
pub insert: Color,
pub normal: Color,
pub non_vi: Color,
}
impl Default for ViColorConfig {
fn default() -> Self {
ViColorConfig {
insert: Color::LightGreen,
normal: Color::LightYellow,
non_vi: Color::Default,
}
}
}